-
Notifications
You must be signed in to change notification settings - Fork 489
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: ko language falls back to ko-KR (#2102)
* test: test i18n languages and fallbacks * test(i18n): use available port * chore: add all local files for ko-KR english has 8 locale files: `ls -lhatr public/locales/en/*.json | wc -l # 8` before this change, ko-KR only had 4 `ls -lhatr public/locales/ko-KR/*.json | wc -l # 4` so I copied them over using `cp -n public/locales/en/*.json public/locales/ko-KR/` after this change `ls -lhatr public/locales/ko-KR/*.json | wc -l # 8` * chore(i18n): ensure app:actions.add has ko translation * fix: only send i18n requests for current language Sends only a single request for lang via i18n-http-backend see i18next/i18next-http-backend#61 * fix: current language displays correctly for fallbacks * test(lib/i18n): test getLanguage function * test(lib/i18n): add getCurrentLanguage test * test(i18n): add test for naming languages in languages.json * fix(i18n): add parser for getting valid locale codes * fix(lib/i18n): use i18n-localeParser * fix(i18n): prevent the lookup of invalid locales fixes #2097 * test(e2e:settings): test language selector * test(e2e/settings): validate that language files are requested * chore: remove untranslated ko-KR files
- Loading branch information
Showing
12 changed files
with
459 additions
and
24 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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,106 @@ | ||
{ | ||
"actions": { | ||
"add": "추가하다", | ||
"apply": "Apply", | ||
"browse": "Browse", | ||
"cancel": "Cancel", | ||
"change": "Change", | ||
"clear": "Clear", | ||
"close": "Close", | ||
"copy": "Copy", | ||
"create": "Create", | ||
"remove": "Remove", | ||
"download": "Download", | ||
"edit": "Edit", | ||
"import": "Import", | ||
"inspect": "Inspect", | ||
"more": "More", | ||
"moreInfo": "More info", | ||
"noThanks": "No thanks", | ||
"ok": "OK", | ||
"pinVerb": "Pin", | ||
"rename": "Rename", | ||
"reset": "Reset", | ||
"save": "Save", | ||
"saving": "Saving…", | ||
"selectAll": "Select all", | ||
"setPinning": "Set pinning", | ||
"submit": "Submit", | ||
"unpin": "Unpin", | ||
"unselectAll": "Unselect all", | ||
"generate": "Generate", | ||
"publish": "Publish", | ||
"downloadCar": "Download as CAR", | ||
"done": "Done" | ||
}, | ||
"cliModal": { | ||
"description": "Paste the following into your terminal to do this task in IPFS via the command line. Remember that you'll need to replace placeholders with your specific parameters." | ||
}, | ||
"nav": { | ||
"bugsLink": "Report a bug", | ||
"codeLink": "See the code" | ||
}, | ||
"status": { | ||
"connectedToIpfs": "Connected to IPFS", | ||
"connectingToIpfs": "Connecting to IPFS…", | ||
"couldNotConnect": "Could not connect to the IPFS API" | ||
}, | ||
"apiAddressForm": { | ||
"placeholder": "Enter a URL (http://127.0.0.1:5001) or a Multiaddr (/ip4/127.0.0.1/tcp/5001)" | ||
}, | ||
"publicGatewayForm": { | ||
"placeholder": "Enter a URL (https://dweb.link)" | ||
}, | ||
"terms": { | ||
"address": "Address", | ||
"addresses": "Addresses", | ||
"advanced": "Advanced", | ||
"agent": "Agent", | ||
"api": "API", | ||
"apiAddress": "API address", | ||
"blocks": "Blocks", | ||
"connection": "Connection", | ||
"downSpeed": "Incoming", | ||
"example": "Example:", | ||
"file": "File", | ||
"files": "Files", | ||
"folder": "Folder", | ||
"folders": "Folders", | ||
"gateway": "Gateway", | ||
"in": "In", | ||
"latency": "Latency", | ||
"loading": "Loading", | ||
"location": "Location", | ||
"name": "Name", | ||
"node": "Node", | ||
"out": "Out", | ||
"peer": "Peer", | ||
"peerId": "Peer ID", | ||
"id": "ID", | ||
"peers": "Peers", | ||
"pinNoun": "Pin", | ||
"pins": "Pins", | ||
"pinStatus": "Pin Status", | ||
"publicKey": "Public key", | ||
"publicGateway": "Public Gateway", | ||
"rateIn": "Rate in", | ||
"rateOut": "Rate out", | ||
"repo": "Repo", | ||
"size": "Size", | ||
"totalIn": "Total in", | ||
"totalOut": "Total out", | ||
"unknown": "Unknown", | ||
"ui": "UI", | ||
"upSpeed": "Outgoing", | ||
"revision": "Revision" | ||
}, | ||
"tour": { | ||
"back": "Back", | ||
"close": "Close", | ||
"finish": "Finish", | ||
"next": "Next", | ||
"skip": "Skip", | ||
"tooltip": "Click this button any time for a guided tour on the current page." | ||
}, | ||
"startTourHelper": "Start tour" | ||
} |
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
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 @@ | ||
/* global describe, it, expect, beforeAll, afterAll */ | ||
// @ts-check | ||
import { createServer } from 'http-server' | ||
import i18n, { localesList } from './i18n.js' | ||
import getPort from 'get-port' | ||
|
||
const backendListenerPort = await getPort({ port: getPort.makeRange(3000, 4000) }) | ||
|
||
const allLanguages = localesList.map(({ locale }) => locale) | ||
|
||
/** | ||
* @type {import('http-server').HTTPServer} | ||
*/ | ||
let httpServer | ||
beforeAll(async function () { | ||
httpServer = createServer({ | ||
root: './public', | ||
cors: true | ||
}) | ||
await httpServer.listen(backendListenerPort) | ||
|
||
// initialize i18n | ||
await i18n.init({ | ||
backend: { | ||
...i18n.options?.backend, | ||
backendOptions: [ | ||
i18n.options?.backend?.backendOptions?.[0], | ||
{ | ||
loadPath: `http://localhost:${backendListenerPort}/locales/{{lng}}/{{ns}}.json` | ||
} | ||
] | ||
} | ||
}) | ||
}) | ||
|
||
afterAll(async function () { | ||
await httpServer.close() | ||
}) | ||
describe('i18n', function () { | ||
it('should have a default language', function () { | ||
expect(i18n.language).toBe('en-US') | ||
expect(i18n.isInitialized).toBe(true) | ||
}) | ||
|
||
it('should return key for non-existent language', function () { | ||
expect(i18n.t('app:actions.add', { lng: 'xx' })).toBe('actions.add') | ||
}) | ||
|
||
allLanguages.concat('ko').forEach((lang) => { | ||
describe(`lang=${lang}`, function () { | ||
it(`should be able to switch to ${lang}`, async function () { | ||
await i18n.changeLanguage(lang) | ||
|
||
expect(i18n.language).toBe(lang) | ||
}) | ||
|
||
it(`should have a key for ${lang}`, async function () { | ||
// key and namespace that don't exist return the key without the leading namespace | ||
expect(await i18n.t('someNs:that.doesnt.exist', { lng: lang })).toBe('that.doesnt.exist') | ||
// missing key on existing namespace returns that key | ||
expect(await i18n.t('app:that.doesnt.exist', { lng: lang })).toBe('that.doesnt.exist') | ||
const langResult = await i18n.t('app:actions.add', { lng: lang }) | ||
expect(langResult).not.toBe('actions.add') | ||
}) | ||
}) | ||
}) | ||
|
||
describe('fallback languages', function () { | ||
/** | ||
* @type {import('i18next').FallbackLngObjList} | ||
*/ | ||
const fallbackLanguages = /** @type {import('i18next').FallbackLngObjList} */(i18n.options.fallbackLng) | ||
for (const lng in fallbackLanguages) { | ||
if (lng === 'default') { | ||
continue | ||
} | ||
const fallbackArr = fallbackLanguages[lng] | ||
fallbackArr.forEach((fallbackLang) => { | ||
it(`fallback '${fallbackLang}' (for '${lng}') is valid`, async function () { | ||
expect(allLanguages).toContain(fallbackLang) | ||
}) | ||
}) | ||
it(`language ${lng} should fallback to ${fallbackArr[0]}`, async function () { | ||
const result = await i18n.t('app:actions.add', { lng }) | ||
const englishResult = await i18n.t('app:actions.add', { lng: 'en' }) | ||
const fallbackResult = await i18n.t('app:actions.add', { lng: fallbackArr[0] }) | ||
expect(result).toBe(fallbackResult) | ||
expect(result).not.toBe(englishResult) | ||
}) | ||
} | ||
}) | ||
}) |
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,46 @@ | ||
/** | ||
* | ||
* @param {object} options | ||
* @param {import('i18next').i18n} options.i18n | ||
* @param {string} options.localeCode | ||
* @param {Record<string, { locale: string, nativeName: string, englishName: string }>} options.languages | ||
* | ||
* @returns {string} | ||
*/ | ||
export default function getValidLocaleCode ({ i18n, localeCode, languages }) { | ||
const info = languages[localeCode] | ||
|
||
if (info != null) { | ||
return localeCode | ||
} | ||
|
||
const fallbackLanguages = i18n.options.fallbackLng[localeCode] | ||
if (info == null && fallbackLanguages != null) { | ||
/** | ||
* check fallback languages before attempting to split a 'lang-COUNTRY' code | ||
* fixed issue with displaying 'English' when i18nLng is set to 'ko' | ||
* discovered when looking into https://github.com/ipfs/ipfs-webui/issues/2097 | ||
*/ | ||
const fallback = fallbackLanguages | ||
for (const locale of fallback) { | ||
const fallbackInfo = languages[locale] | ||
|
||
if (fallbackInfo != null) { | ||
return fallbackInfo.locale | ||
} | ||
} | ||
} | ||
|
||
// if we haven't got the info in the `languages.json` we split it to get the language | ||
const langOnly = localeCode.split('-')[0] | ||
if (languages[langOnly]) { | ||
return langOnly | ||
} | ||
// if the provided localeCode doesn't have country, but we have a supported language for a specific country, we return that | ||
const langWithCountry = Object.keys(languages).find((key) => key.startsWith(localeCode)) | ||
if (langWithCountry) { | ||
return langWithCountry | ||
} | ||
|
||
return 'en' | ||
} |
Oops, something went wrong.