Update localization files + references (#4556)

* Initial plan

* Add localization support to NameChangeModal component

Co-authored-by: gabek <414923+gabek@users.noreply.github.com>

* Add NameChangeModal translations to English language file

Co-authored-by: gabek <414923+gabek@users.noreply.github.com>

* fix(i18n): fix localization keys

* chore(test): add i18n test

* chore(i18n): update translation script

* chore(i18n): reorgnize translation keys and update components

* chore: fix linting warnings

* chore(i18n): update all the language files

* feat(i18n): add last live ago i18n key

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: gabek <414923+gabek@users.noreply.github.com>
Co-authored-by: Gabe Kangas <gabek@real-ity.com>
This commit is contained in:
Copilot
2025-09-15 19:27:56 -07:00
committed by GitHub
parent 401b5897e2
commit 1cf923a5af
46 changed files with 6053 additions and 4639 deletions

View File

@ -38,7 +38,14 @@ function sortObjectKeys(obj) {
function scanTranslationKeys() {
const files = glob.sync('**/*.{ts,tsx,js,jsx}', {
ignore: ['node_modules/**', '.next/**', 'out/**'],
ignore: [
'node_modules/**',
'.next/**',
'out/**',
'storybook-static/**',
'coverage/**',
'.storybook/**',
],
});
const results = {};
@ -101,6 +108,57 @@ function scanTranslationKeys() {
defaultText || `<strong><em>Missing translation ${key}: Please report</em></strong>`;
}
},
CallExpression(p) {
const { node } = p;
// Check if this is a call to t() function
if (node.callee.type !== 'Identifier' || node.callee.name !== 't') return;
// Check if the first argument is a Localization key
if (node.arguments.length === 0) return;
const firstArg = node.arguments[0];
let key = null;
// Handle t(Localization.Frontend.NameChangeModal.placeholder)
if (firstArg.type === 'MemberExpression') {
const dotPath = getDotPath(firstArg);
if (dotPath) {
key = dotPath;
}
}
// Handle t("some.string.key") - but only if it looks like a translation key
else if (firstArg.type === 'StringLiteral') {
const { value } = firstArg;
// Only include string literals that follow our translation key pattern:
// - Must have dots for hierarchy (e.g., Frontend.Component.key)
// - Must start with a capital letter (namespace convention)
// - Must not contain spaces (translation keys shouldn't have spaces)
// - Must not be common JS patterns like prototype methods
if (
value.includes('.') &&
/^[A-Z][a-zA-Z0-9]*\./.test(value) &&
!value.includes(' ') &&
!value.includes('prototype') &&
!value.includes('()') &&
value.split('.').length >= 2 &&
value.split('.').length <= 5
) {
// Reasonable depth for translation keys
key = value;
}
}
if (key) {
// For t() calls, we don't have defaultText, so use the fallback
if (!results[key]) {
console.log(`[i18n] Found t() call with key: ${key} in ${file}`);
}
results[key] =
results[key] || `<strong><em>Missing translation ${key}: Please report</em></strong>`;
}
},
});
}
@ -164,7 +222,7 @@ function updateTranslationFile(flatTranslations) {
if (changed) {
const merged = sortObjectKeys(mergeDeep(existing, newNestedTranslations));
fs.writeFileSync(TRANSLATIONS_PATH, JSON.stringify(merged, null, 2));
fs.writeFileSync(TRANSLATIONS_PATH, JSON.stringify(merged, null, '\t'));
console.log(`[i18n] Updated ${TRANSLATIONS_PATH}`);
} else {
console.log('[i18n] No new keys to add.');