mirror of
https://github.com/sipeed/NanoKVM.git
synced 2026-09-11 00:22:56 -05:00
Merge pull request #686 from pekishev/paste_rus
Add support for pasting russian text
This commit is contained in:
@@ -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} // §
|
||||
|
||||
@@ -74,7 +74,8 @@ const de = {
|
||||
virtual: 'Tastatur',
|
||||
ctrlaltdel: 'Ctrl+Alt+Del',
|
||||
dropdownEnglish: 'Englisch',
|
||||
dropdownGerman: 'Deutsch'
|
||||
dropdownGerman: 'Deutsch',
|
||||
dropdownRussian: 'Russisch'
|
||||
},
|
||||
mouse: {
|
||||
title: 'Maus',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -73,7 +73,10 @@ const ru = {
|
||||
placeholder: 'Текст для ввода',
|
||||
submit: 'Вставить',
|
||||
virtual: 'Клавиатура',
|
||||
ctrlaltdel: 'Ctrl+Alt+Del'
|
||||
ctrlaltdel: 'Ctrl+Alt+Del',
|
||||
dropdownEnglish: 'Английский',
|
||||
dropdownGerman: 'Немецкий',
|
||||
dropdownRussian: 'Русский'
|
||||
},
|
||||
mouse: {
|
||||
title: 'Мышь',
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user