-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add new
isRTL
function to check whether a given, or the curre…
…nt, language is right-to-left read Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
- Loading branch information
Showing
5 changed files
with
163 additions
and
71 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/** | ||
* Returns the user's locale | ||
*/ | ||
export function getLocale(): string { | ||
return document.documentElement.dataset.locale || 'en' | ||
} | ||
|
||
/** | ||
* Returns user's locale in canonical form | ||
* E.g. `en-US` instead of `en_US` | ||
*/ | ||
export function getCanonicalLocale(): string { | ||
return getLocale().replace(/_/g, '-') | ||
} | ||
|
||
/** | ||
* Returns the user's language | ||
*/ | ||
export function getLanguage(): string { | ||
return document.documentElement.lang || 'en' | ||
} | ||
|
||
/** | ||
* Check whether the current, or a given, language is read right-to-left | ||
* | ||
* @param language Language code to check, defaults to current language | ||
*/ | ||
export function isRTL(language?: string): boolean { | ||
const languageCode = language || getLanguage() | ||
|
||
// Source: https://meta.wikimedia.org/wiki/Template:List_of_language_names_ordered_by_code | ||
const rtlLanguages = [ | ||
/* eslint-disable no-multi-spaces */ | ||
'ae', // Avestan | ||
'ar', // 'العربية', Arabic | ||
'arc', // Aramaic | ||
'arz', // 'مصرى', Egyptian | ||
'bcc', // 'بلوچی مکرانی', Southern Balochi | ||
'bqi', // 'بختياري', Bakthiari | ||
'ckb', // 'Soranî / کوردی', Sorani | ||
'dv', // Dhivehi | ||
'fa', // 'فارسی', Persian | ||
'glk', // 'گیلکی', Gilaki | ||
'ha', // 'هَوُسَ', Hausa | ||
'he', // 'עברית', Hebrew | ||
'khw', // 'کھوار', Khowar | ||
'ks', // 'कॉशुर / کٲشُر', Kashmiri | ||
'ku', // 'Kurdî / كوردی', Kurdish | ||
'mzn', // 'مازِرونی', Mazanderani | ||
'nqo', // 'ߒߞߏ', N’Ko | ||
'pnb', // 'پنجابی', Western Punjabi | ||
'ps', // 'پښتو', Pashto, | ||
'sd', // 'سنڌي', Sindhi | ||
'ug', // 'Uyghurche / ئۇيغۇرچە', Uyghur | ||
'ur', // 'اردو', Urdu | ||
'uzs', // 'اوزبیکی', Uzbek Afghan | ||
'yi', // 'ייִדיש', Yiddish | ||
/* eslint-enable no-multi-spaces */ | ||
] | ||
|
||
// special case for Uzbek Afghan | ||
if ((language || getCanonicalLocale()).startsWith('uz-AF')) { | ||
return true | ||
} | ||
|
||
return rtlLanguages.includes(languageCode) | ||
} |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import { | ||
getCanonicalLocale, | ||
getLanguage, | ||
getLocale, | ||
isRTL | ||
} from '../lib/locale' | ||
|
||
const setLocale = (locale: string) => document.documentElement.setAttribute('data-locale', locale) | ||
const setLanguage = (lang: string) => document.documentElement.setAttribute('lang', lang) | ||
|
||
describe('getCanonicalLocale', () => { | ||
afterEach(() => { | ||
setLocale('') | ||
}) | ||
|
||
it('Returns primary locales as is', () => { | ||
setLocale('de') | ||
expect(getCanonicalLocale()).toEqual('de') | ||
setLocale('zu') | ||
expect(getCanonicalLocale()).toEqual('zu') | ||
}) | ||
|
||
it('Returns extended locales with hyphens', () => { | ||
setLocale('az_Cyrl_AZ') | ||
expect(getCanonicalLocale()).toEqual('az-Cyrl-AZ') | ||
setLocale('de_DE') | ||
expect(getCanonicalLocale()).toEqual('de-DE') | ||
}) | ||
}) | ||
|
||
test('getLanguage', () => { | ||
document.documentElement.removeAttribute('lang') | ||
// Expect fallback | ||
expect(getLanguage()).toBe('en') | ||
setLanguage('') | ||
expect(getLanguage()).toBe('en') | ||
|
||
// Expect value | ||
setLanguage('zu') | ||
expect(getLanguage()).toBe('zu') | ||
}) | ||
|
||
test('getLocale', () => { | ||
document.documentElement.removeAttribute('data-locale') | ||
// Expect fallback | ||
expect(getLocale()).toBe('en') | ||
setLocale('') | ||
expect(getLocale()).toBe('en') | ||
|
||
// Expect value | ||
setLocale('de_DE') | ||
expect(getLocale()).toBe('de_DE') | ||
}) | ||
|
||
describe('isRTL', () => { | ||
beforeEach(() => document.documentElement.removeAttribute('data-locale')) | ||
|
||
it('fallsback to English which is LTR', () => { | ||
// Expect fallback which is English = LTR | ||
expect(isRTL()).toBe(false) | ||
}) | ||
|
||
it('uses the given argument over the current language', () => { | ||
// If a value is given it should use that language over the fallback | ||
expect(isRTL('ar')).toBe(true) | ||
setLanguage('ar') | ||
expect(isRTL('de')).toBe(false) | ||
}) | ||
|
||
it('without an argument the current language is used', () => { | ||
// It uses the configured language | ||
setLanguage('he') | ||
expect(isRTL()).toBe(true) | ||
}) | ||
|
||
it('without an argument the current language is used', () => { | ||
// It uses the configured language | ||
setLanguage('he') | ||
expect(isRTL()).toBe(true) | ||
}) | ||
|
||
it('handles Uzbek Afghan correctly', () => { | ||
// Given as argument | ||
expect(isRTL('uz')).toBe(false) | ||
expect(isRTL('uz-AF')).toBe(true) | ||
|
||
// configured as current language | ||
setLanguage('uz') | ||
setLocale('uz_AF') | ||
expect(isRTL()).toBe(true) | ||
}) | ||
}) |
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