feat(i18n): Arabic, Hebrew, Persian and Urdu, and a layout that mirrors; release v6.4.0
Four right-to-left languages at /ar/, /he/, /fa/ and /ur/ — thirteen in all. The layout no longer has a left and a right, it has a start and an end: the margins, insets and corners are CSS logical properties now, so they follow dir on <html>. Directional glyphs flip; keys, safety codes and session descriptors are pinned left-to-right so bidi cannot reorder what two people compare against each other's screens. Also fixed: the Service Worker was registered as './sw.js', which 404s from every locale subdirectory, so twelve of the thirteen pages had no worker at all. And the bundler ran before the dictionaries were generated, so a newly added language could reach the page ahead of the app that renders it.
This commit is contained in:
@@ -110,6 +110,44 @@ export function currentLocale() {
|
||||
return resolvedLocale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writing direction of a locale. Arabic, Hebrew, Persian and Urdu read right to left,
|
||||
* and the whole layout — not just the text — has to follow: an avatar that sits before
|
||||
* a name in English sits after it in Arabic.
|
||||
*
|
||||
* The generated page already carries dir on <html>, so nothing here needs to apply it
|
||||
* at load. This exists for the handful of decisions CSS cannot express on its own —
|
||||
* which way an arrow points, which edge a drawer slides in from.
|
||||
*/
|
||||
export function localeDir(code = currentLocale()) {
|
||||
return LOCALE_META[code]?.dir === 'rtl' ? 'rtl' : 'ltr';
|
||||
}
|
||||
|
||||
export function isRTL(code = currentLocale()) {
|
||||
return localeDir(code) === 'rtl';
|
||||
}
|
||||
|
||||
/**
|
||||
* +1 or -1, for arithmetic on a horizontal offset: a swipe threshold, a translate, the
|
||||
* side a sheet enters from. `x * direction()` is the whole of what a mirrored gesture
|
||||
* needs, and it reads better than an `isRTL ? -x : x` at every call site.
|
||||
*/
|
||||
export function direction(code = currentLocale()) {
|
||||
return isRTL(code) ? -1 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a fragment to be laid out left to right inside right-to-left text.
|
||||
*
|
||||
* Bidi reordering is done by the browser on the rendered text, and it mangles exactly
|
||||
* the strings this app is made of: a key fingerprint, a base64 session descriptor, a
|
||||
* URL, a version number. In an RTL paragraph "a1b2:c3d4" can come out as "c3d4:a1b2" —
|
||||
* the characters are all there, so nothing looks broken, and the reader compares the
|
||||
* wrong thing against their peer's screen. Any element showing machine text gets these
|
||||
* props.
|
||||
*/
|
||||
export const LTR_TEXT = { dir: 'ltr', style: { unicodeBidi: 'isolate', textAlign: 'start' } };
|
||||
|
||||
/**
|
||||
* A locale the visitor would probably rather read, when it is not the one they are on.
|
||||
* Used to offer a link, never to redirect: an automatic redirect sends Googlebot —
|
||||
@@ -150,6 +188,9 @@ export function languageLinks({ pathname = '/', active = DEFAULT_LOCALE } = {})
|
||||
label: LOCALE_META[code]?.nativeName || code,
|
||||
// Short code for the collapsed switcher.
|
||||
abbr: LOCALE_META[code]?.abbr || code.toUpperCase(),
|
||||
// The row renders a name in its own script, so it needs its own direction:
|
||||
// "العربية" laid out left-to-right is the word spelled backwards.
|
||||
dir: LOCALE_META[code]?.dir || 'ltr',
|
||||
isCurrent: code === active,
|
||||
}));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user