Last active
April 12, 2022 05:10
-
-
Save eligrey/c15d8ec3e500dcfc3a5ec0256ce07c2b to your computer and use it in GitHub Desktop.
Simple language matcher
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { matchLanguages, getNearestSupportedLanguage } from './match-languages'; | |
const supportedLanguages = ['en-GB', 'fr']; | |
console.log('navigator.languages: ', navigator.languages); | |
const matches = matchLanguages(navigator.languages, supportedLanguages); | |
console.log('preferred language matches:', matches); | |
const nearest = getNearestSupportedLanguage(matches, supportedLanguages); | |
console.log('nearest matching supported language:', nearest); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Get all potential sub-languages from a given ISO 639-1 language code | |
* | |
* @param langCode - ISO 639-1 format language code | |
* @returns Array of potential sub-languages, sorted by most to least specific | |
*/ | |
const getAllSubLanguages = (langCode: string): string[] => | |
langCode | |
.toLowerCase() | |
.split('-') | |
.flatMap((_, i, tags) => tags.slice(0, i + 1).join('-')) | |
.reverse(); | |
/** | |
* Match preferred language list against a supported languages list | |
* | |
* @param preferred - Sorted language list in order of most preferable to least preferable | |
* @param supported - List of supported languages to match from | |
* @returns Preferred languages (including sub-language matches) that match supported languages list | |
*/ | |
export const matchLanguages = ( | |
preferred: string[], | |
supported: string[], | |
): string[] => { | |
const matches = new Set<string>(); | |
const allSupportedLanguages = supported.flatMap(getAllSubLanguages); | |
return preferred.flatMap(getAllSubLanguages).filter((language) => { | |
if (!allSupportedLanguages.includes(language)) { | |
return false; | |
} | |
const unique = !matches.has(language); | |
if (unique) { | |
matches.add(language); | |
} | |
return unique; | |
}); | |
}; | |
/** | |
* Get nearest matching language from a list of supported languages | |
* | |
* @param preferred - Sorted language list in order of most preferable to least preferable | |
* @param supported - List of supported languages to match from | |
* @returns Nearest supported language, sorted by preferred language list | |
*/ | |
export const getNearestSupportedLanguage = ( | |
preferred: string[], | |
supported: string[], | |
): string | undefined => | |
supported.find((language) => | |
getAllSubLanguages(language).some((lang) => | |
preferred.some((preferredLang) => | |
preferredLang.toLowerCase() === lang | |
) | |
), | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment