import type { Config } from '../locale/config.ts'; import type { Translations } from '../locale/translations.ts'; import { deepGet, deepListKeys } from './helpers.ts'; const localeSpecificFlagAlt = /flags_alt\.-(.+)-/; export function listMissingTranslations( translations: Translations, baseTranslations: Translations, config: Config, ): string[] { const expectedTranslations = [...deepListKeys(baseTranslations)]; return expectedTranslations.filter((k) => { function keyMatches(...pats: string[]): boolean { for (const pat of pats) { if (pat.endsWith('.')) { if (k.startsWith(pat)) { return true; } } else { if (k === pat) { return true; } } } return false; } function has(k: string): boolean { return deepGet(translations, k) !== undefined; } if (has(k)) { return false; } // macrolanguage.* keys are only required for macrolanguage locales if (!config.macrolanguage?.enabled && keyMatches('macrolanguage.')) { return false; } // FAQ entries are fully customizable for a language version. if (keyMatches('faq.')) { return false; } // disclaimer is only required when optional translations are present for a non-English locale if ((!has('terms.content') && !has('privacy.content') || config.locale === 'en') && keyMatches('terms.translationDisclaimer') ) { return false; } // optional keys if (keyMatches( 'home.welcome', 'contact.faq', 'contact.technical', 'contact.hate', 'contact.team.extra', 'contact.team.join.', 'user.login.help', 'terms.content.', 'terms.update.', 'privacy.content.', 'privacy.consent.', )) { return false; } if (!has('home.welcome') && keyMatches('home.intro')) { return false; } if (!config.pronouns.enabled && keyMatches( 'pronouns.', 'home.header', 'home.headerLong', 'home.pronouns', 'home.generator.', 'profile.pronouns', 'profile.pronounsInfo', 'profile.pronounsNotFound', 'profile.share.pronouns', )) { return false; } if (!config.pronouns.exampleCategories && keyMatches('pronouns.examples.shuffleNamed')) { return false; } if (!config.pronouns.generator?.enabled && keyMatches('home.generator.')) { return false; } if (!config.pronouns.generator?.slashes && keyMatches('pronouns.slashes.')) { return false; } if (!config.pronouns.plurals && keyMatches( 'pronouns.plural', 'pronouns.slashes.plural', 'pronouns.slashes.pluralHonorific', )) { return false; } if (!config.pronouns.null && keyMatches('pronouns.null.')) { return false; } if ((!config.pronouns.null || !config.pronouns.null.morphemes) && keyMatches('pronouns.null.button', 'pronouns.null.base')) { return false; } if (!config.pronouns.emoji && keyMatches('pronouns.emoji.')) { return false; } if (!config.pronouns.ask && keyMatches('pronouns.ask.')) { return false; } // locale specific flags const match = k.match(localeSpecificFlagAlt); if (match && match[1] !== config.locale) { return false; } if (!config.pronouns.honorifics && keyMatches('pronouns.slashes.pluralHonorific')) { return false; } if (!config.pronouns.comprehensive && keyMatches('pronouns.comprehensive.')) { return false; } if (!config.links.enabled && keyMatches('links.')) { return false; } if (!config.sources.enabled && keyMatches('sources.')) { return false; } if (!config.nouns.enabled && keyMatches('nouns.')) { return false; } if (!config.nouns.nonbinary && keyMatches('nouns.nonbinary')) { return false; } if (config.nouns.categories?.length === 0 && keyMatches('nouns.categories')) { return false; } if (!config.nouns.templates?.enabled && keyMatches('nouns.template.')) { return false; } if (!config.nouns.conventions?.enabled && keyMatches('nouns.conventions.', 'nouns.submit.regular.', 'nouns.submit.irregular.')) { return false; } if (!config.nouns.declension?.enabled && keyMatches('nouns.declension.')) { return false; } if (!config.terminology.enabled && keyMatches('terminology.')) { return false; } if (!config.calendar?.enabled && keyMatches('calendar.')) { return false; } if (!config.blog && keyMatches('links.blogLatest', 'links.blogFeed', 'links.blogReact', 'links.blogReactAuthRequired')) { return false; } if (!config.api?.enabled && keyMatches('profile.header', 'api.example', 'api.query')) { return false; } if (!config.english.enabled && keyMatches('english.')) { return false; } return true; }); }