lbry-desktop/ui/i18n.js
infinite-persistence 5948ee0d80
i18n: restore ability to retrieve new i18n strings
## Issue
In the original Desktop code, new strings encountered during runtime will be automatically added to the local `app-strings.json` file. The feature is unavailable in Web because writing to file would require explicit permissions.

## Change
Partially restore the functionality by saving the strings to memory and retrieving it from the console via `copy(window.new_strings)`. It's a little bit of manual work, but I think it is good as it forces a sanity check before committing (previously, experimental/developmental strings are committed and being translated in Transifex).
2022-01-03 10:36:12 +08:00

81 lines
2.6 KiB
JavaScript

// @flow
import { isLocalStorageAvailable } from 'util/storage';
const isProduction = process.env.NODE_ENV === 'production';
const localStorageAvailable = isLocalStorageAvailable();
window.i18n_messages = window.i18n_messages || {};
/**
* Collects new i18n strings encountered during runtime.
* The output can be retrieved and pasted into app-strings.json.
*
* @param message
*/
function saveMessageWeb(message) {
// @if process.env.NODE_ENV!='production'
if (!window.app_strings) {
return;
}
if (!window.new_strings) {
console.log('Copy new i18n to clipboard:%c copy(window.new_strings)', 'color:yellow'); // eslint-disable-line
}
window.new_strings = window.new_strings || {};
if (!window.app_strings[message] && !window.new_strings[message]) {
window.new_strings[message] = removeContextMetadata(message);
}
// @endif
}
function removeContextMetadata(message) {
// Example string entries with context-metadata:
// "About --[About section in Help Page]--": "About",
// "About --[tab title in Channel Page]--": "About",
const CONTEXT_BEGIN = '--[';
const CONTEXT_FINAL = ']--';
// If the resolved string still contains the context-metadata, then it's one of the following:
// 1. In development mode, where 'en.json' in the server hasn't been updated with the string yet.
// 2. Translator made a mistake of not ignoring the context string.
// In either case, we'll revert to the English version.
const begin = message.lastIndexOf(CONTEXT_BEGIN);
if (begin > 0 && message.endsWith(CONTEXT_FINAL)) {
// Strip away context:
message = message.substring(0, begin);
// No trailing spaces should be allowed in the string database anyway, because that is hard to translate
// (can't see in Transifex; might not make sense in other languages; etc.).
// With that, we can add a space before the context-metadata to make it neat, and trim both cases here:
message = message.trimEnd();
}
return message;
}
export function __(message: string, tokens: { [string]: string }) {
if (!message) {
return '';
}
const language = localStorageAvailable
? window.localStorage.getItem('language') || 'en'
: window.navigator.language.slice(0, 2) || 'en';
if (!isProduction) {
saveMessageWeb(message);
}
let translatedMessage = window.i18n_messages[language] ? window.i18n_messages[language][message] || message : message;
translatedMessage = removeContextMetadata(translatedMessage);
if (!tokens) {
return translatedMessage;
}
return translatedMessage.replace(/%([^%]+)%/g, ($1, $2) => {
return tokens.hasOwnProperty($2) ? tokens[$2] : $2;
});
}