Merge pull request #686 from pekishev/paste_rus

Add support for pasting russian text
This commit is contained in:
wenjie
2025-12-23 15:31:06 +08:00
committed by GitHub
5 changed files with 80 additions and 17 deletions

View File

@@ -20,25 +20,25 @@ type PasteReq struct {
}
func LangueSwitch(base map[rune]Char, lang string) map[rune]Char {
// wenn kein lang angegeben → Standardmap zurück
// if no language is specified → return base map
if lang == "" {
return base
}
// immer Kopie erstellen
// always create a copy of the base map
m := copyMap(base)
switch lang {
case "de":
// Y tauschen
// swap Y
m['y'] = Char{0, 29}
m['Y'] = Char{2, 29}
// Z tauschen
// swap Z
m['z'] = Char{0, 28}
m['Z'] = Char{2, 28}
// deutsche Sonderzeichen hinzufügen oder remappen
// add German special characters or remap them
m['\u00E4'] = Char{0, 52} // ä
m['\u00C4'] = Char{2, 52} // Ä
m['\u00F6'] = Char{0, 51} // ö
@@ -47,8 +47,8 @@ func LangueSwitch(base map[rune]Char, lang string) map[rune]Char {
m['\u00DC'] = Char{2, 47} // Ü
m['\u00DF'] = Char{0, 45} // ß
//Tauschen
m['^'] = Char{0, 53} // muss doppelt sein
// swap special characters
m['^'] = Char{0, 53} // must be double
m['/'] = Char{2, 36} // Shift + 7
m['('] = Char{2, 37} // Shift + 8
m['&'] = Char{2, 35} // Shift + 6
@@ -75,7 +75,7 @@ func LangueSwitch(base map[rune]Char, lang string) map[rune]Char {
m['-'] = Char{0, 56} // Shift + -
m['_'] = Char{2, 56} // Shift + -
//neu
// new special characters
m['\u00B4'] = Char{0, 46} // ´
m['\u00B0'] = Char{2, 53} // °
m['\u00A7'] = Char{2, 32} // §

View File

@@ -74,7 +74,8 @@ const de = {
virtual: 'Tastatur',
ctrlaltdel: 'Ctrl+Alt+Del',
dropdownEnglish: 'Englisch',
dropdownGerman: 'Deutsch'
dropdownGerman: 'Deutsch',
dropdownRussian: 'Russisch'
},
mouse: {
title: 'Maus',

View File

@@ -80,7 +80,8 @@ const en = {
'Clipboard permission denied. Please allow clipboard access in your browser.',
clipboardReadError: 'Failed to read clipboard',
dropdownEnglish: 'English',
dropdownGerman: 'German'
dropdownGerman: 'German',
dropdownRussian: 'Russian'
},
mouse: {
title: 'Mouse',

View File

@@ -73,7 +73,10 @@ const ru = {
placeholder: 'Текст для ввода',
submit: 'Вставить',
virtual: 'Клавиатура',
ctrlaltdel: 'Ctrl+Alt+Del'
ctrlaltdel: 'Ctrl+Alt+Del',
dropdownEnglish: 'Английский',
dropdownGerman: 'Немецкий',
dropdownRussian: 'Русский'
},
mouse: {
title: 'Мышь',

View File

@@ -28,7 +28,8 @@ export const Paste = () => {
const languages = [
{ value: 'en', label: t('keyboard.dropdownEnglish') },
{ value: 'de', label: t('keyboard.dropdownGerman') }
{ value: 'de', label: t('keyboard.dropdownGerman') },
{ value: 'ru', label: t('keyboard.dropdownRussian') }
];
useEffect(() => {
@@ -37,7 +38,7 @@ export const Paste = () => {
function onChange(e: ChangeEvent<HTMLTextAreaElement>) {
const value = e.target.value;
setStatus(isASCII(value) ? '' : 'error');
setStatus(isValidForLanguage(value, langue) ? '' : 'error');
setInputValue(value);
}
@@ -61,12 +62,50 @@ export const Paste = () => {
setIsReadingClipboard(false);
}
}
// Extended RU → EN translation including punctuation
function translateRuToEnWithPunctuation(value: string): string {
const letterMap: Record<string, string> = {
'ё': '`',
'й': 'q', 'ц': 'w', 'у': 'e', 'к': 'r', 'е': 't', 'н': 'y', 'г': 'u', 'ш': 'i',
'щ': 'o', 'з': 'p', 'х': '[', 'ъ': ']',
'ф': 'a', 'ы': 's', 'в': 'd', 'а': 'f', 'п': 'g', 'р': 'h', 'о': 'j', 'л': 'k',
'д': 'l', 'ж': ';', 'э': '\'',
'я': 'z', 'ч': 'x', 'с': 'c', 'м': 'v', 'и': 'b', 'т': 'n', 'ь': 'm', 'б': ',', 'ю': '.',
};
const punctuationMap: Record<string, string> = {
'"': '@',
'№': '#',
';': '$',
':': '^',
'?': '&',
'Ё': '~',
'/': '|',
'.': '/',
',': '?',
};
return Array.from(value).map((ch) => {
const lower = ch.toLowerCase();
if (letterMap[lower]) {
const translated = letterMap[lower];
return ch === lower ? translated : translated.toUpperCase();
}
if (punctuationMap[ch]) {
return punctuationMap[ch];
}
return ch;
}).join('');
}
function submit() {
if (isLoading || !inputValue) return;
setIsLoading(true);
paste(inputValue, langue)
const textToSend = langue === 'ru' ? translateRuToEnWithPunctuation(inputValue) : inputValue;
paste(textToSend, langue)
.then((rsp) => {
if (rsp.code !== 0) {
setErrMsg(rsp.msg);
@@ -91,9 +130,28 @@ export const Paste = () => {
setIsKeyboardEnable(!open);
}
function isASCII(value: string) {
for (let i = 0; i < value.length; i++) {
if (value.charCodeAt(i) > 127) {
function isValidForLanguage(value: string, selectedLangue: string) {
const isRussian = selectedLangue === 'ru';
for (const ch of value) {
const code = ch.codePointAt(0) ?? 0;
if (isRussian) {
// For Russian language, allow Cyrillic letters and special characters
// that can be typed on Russian keyboard (but not English letters)
if (
(code >= 0x0410 && code <= 0x042F) || // (А-Я)
(code >= 0x0430 && code <= 0x044F) || // (а-я)
code === 0x0401 || // (Ё)
code === 0x0451 || // (ё)
(code >= 0x20 && code <= 0x7E && !(code >= 0x41 && code <= 0x5A) && !(code >= 0x61 && code <= 0x7A)) // Special chars, digits, space, but not English letters
) {
continue;
}
return false;
} else {
// For English/German, only allow ASCII
if (code <= 0x7F) continue;
return false;
}
}