feat(Text to NATO): add other languages, upper/lower and other

Add support for many languages and countries ((International), (France), (Belgium), (Switzerland), (Québec), (Germany, 2022), (Austria), (Germany, informal, 2022), (Netherlands), Italian, Spanish, (Brazil), (Portugal), Swedish, Danish, Norwegian, Finnish, Turkish, Romanian, Czech, Yugoslav, Serbian, Slovene, Russian, Korean, Greek, Japanese)
Handle uppercase/lowercase and some punctuations
Fix #794
This commit is contained in:
sharevb 2024-04-02 08:57:13 +02:00 committed by ShareVB
parent d3b32cc14e
commit 1b1be10762
4 changed files with 1644 additions and 42 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,28 +1,29 @@
export const natoAlphabet = [
'Alpha',
'Bravo',
'Charlie',
'Delta',
'Echo',
'Foxtrot',
'Golf',
'Hotel',
'India',
'Juliet',
'Kilo',
'Lima',
'Mike',
'November',
'Oscar',
'Papa',
'Quebec',
'Romeo',
'Sierra',
'Tango',
'Uniform',
'Victor',
'Whiskey',
'X-ray',
'Yankee',
'Zulu',
export const allLanguagesAndCountries = [
'(International)',
'(France)',
'(Belgium)',
'(Switzerland)',
'(Québec)',
'(Germany, 2022)',
'(Austria)',
'(Germany, informal, 2022)',
'(Netherlands)',
'Italian',
'Spanish',
'(Brazil)',
'(Portugal)',
'Swedish',
'Danish',
'Norwegian',
'Finnish',
'Turkish',
'Romanian',
'Czech',
'Yugoslav',
'Serbian',
'Slovene',
'Russian',
'Korean',
'Greek',
'Japanese',
];

View file

@ -1,19 +1,32 @@
import { natoAlphabet } from './text-to-nato-alphabet.constants';
import allAlphabets from './nato.alphabets.json';
type AllALphabetsKeys = keyof typeof allAlphabets[0];
export { textToNatoAlphabet };
function getLetterPositionInAlphabet({ letter }: { letter: string }) {
return letter.toLowerCase().charCodeAt(0) - 'a'.charCodeAt(0);
}
function textToNatoAlphabet({ text }: { text: string }) {
function textToNatoAlphabet({ text, langOrCountry = '(International)' }: { text: string; langOrCountry: string }) {
const charRegex = new RegExp(
`(${
allAlphabets
.sort((a, b) => b.Letter.length - a.Letter.length)
.filter(a => a[langOrCountry as AllALphabetsKeys])
.map(a => a.Letter)
.join('|')
}|.)`,
'gi');
return text
.split('')
.map((character) => {
const alphabetIndex = getLetterPositionInAlphabet({ letter: character });
const natoWord = natoAlphabet[alphabetIndex];
.replace(/\s/g, ' ')
.replace(
charRegex,
(character) => {
const searchChar = character.toUpperCase();
const isUpper = character[0].toUpperCase() === character[0];
const alphabetLetter = allAlphabets.find(letter => letter.Letter === searchChar);
if (alphabetLetter && alphabetLetter[langOrCountry as AllALphabetsKeys]) {
const natoWord = alphabetLetter[langOrCountry as AllALphabetsKeys] || '';
return ` ${isUpper ? natoWord.toUpperCase() : natoWord.toLowerCase()} `;
}
return natoWord ?? character;
})
.join(' ');
return ` (${character}) `;
});
}

View file

@ -1,14 +1,22 @@
<script setup lang="ts">
import { textToNatoAlphabet } from './text-to-nato-alphabet.service';
import { allLanguagesAndCountries } from './text-to-nato-alphabet.constants';
import { useCopy } from '@/composable/copy';
const lang = useStorage('text-to-nato:lang', '(International)');
const input = ref('');
const natoText = computed(() => textToNatoAlphabet({ text: input.value }));
const natoText = computed(() => textToNatoAlphabet({ text: input.value, langOrCountry: lang.value }));
const { copy } = useCopy({ source: natoText, text: 'NATO alphabet string copied.' });
</script>
<template>
<div>
<c-select
v-model:value="lang"
:options="allLanguagesAndCountries"
searchable
/>
<c-input-text
v-model:value="input"
label="Your text to convert to NATO phonetic alphabet"
@ -19,7 +27,7 @@ const { copy } = useCopy({ source: natoText, text: 'NATO alphabet string copied.
<div v-if="natoText">
<div mb-2>
Your text in NATO phonetic alphabet
Your text in NATO phonetic alphabet ({{ lang }})
</div>
<c-card>
{{ natoText }}