-
Notifications
You must be signed in to change notification settings - Fork 1
Home
Welcome to the i18n-hunt wiki!
This page documents the source-code and locale-file patterns currently supported by i18n-hunt.
i18n-hunt prefers conservative detection over aggressive guessing. The goal is to minimize false positives while still surfacing genuinely unused translation keys.
- Source files:
.ts,.tsx,.js,.jsx - Locale files:
.json - Locale keys are flattened from nested JSON objects
Example:
{
"form": {
"email": "Email"
}
}Flattened key:
form.emailconst { t } = useTranslation("Auth/Login");
t("title");Namespace arrays are also supported:
const { t } = useTranslation(["Auth/Login", "Common"]);
t("sharedFallback");i18next.t("Auth/Login:i18nextOnly");t("Auth/Login:colonUsed");t("optionNsOnly", { ns: "Auth/Login" });<Trans i18nKey="transOnly" ns="Common" />i18n-hunt classifies key usage into three resolution types.
A key that can be resolved exactly.
t("form.email");A partially dynamic key with a stable leading prefix.
t(`form.${field}`);Detected prefix:
form.Any locale key that starts with the detected prefix is protected from being reported as unused.
A key expression that cannot be resolved safely.
t(`${section}.title`);Dynamic usages are tracked, but they are not used aggressively to mark keys as used.
Template literals with no expressions are treated as static keys:
t(`title`);Template literals with a stable leading string are treated as prefixes:
t(`form.${field}`);Template literals without a stable leading prefix are treated as dynamic:
t(`${section}.title`);Local const string values can be resolved:
const key = "title";
t(key);Conditional expressions are analyzed when both branches can be resolved:
t(cond ? "a" : "b");Logical fallbacks are supported:
t(getMaybeKey() || "title");
t(getMaybeNullKey() ?? "form.submit");Some logical expressions are treated conservatively:
t(flag && "title");In this case, the usage is treated as dynamic overall.
t(["title", "description"]);Array elements are analyzed individually.
When a callback parameter is used as the translation key, supported iterator patterns can be resolved:
["form.email", "form.password"].map((key) => t(key));OPTIONS.forEach((key) => t(key));const object maps are supported for static and computed member access:
const keyByState = {
created: "mapCreated",
deleted: "mapDeleted",
};
t(keyByState[state]);
t(keyByState.deleted);Top-level function declarations returning translation keys can be inferred:
function getErrorKey() {
return Math.random() > 0.5
? "errors.network"
: "errors.invalidCredentials";
}
t(getErrorKey());Server-side translator helpers are supported when the namespace can be resolved:
const t = await getServerTranslate("Accounting");
t("serverOnly");Source and locale scanning support glob excludes through config.
src_exclude = ["**/*.test.ts", "legacy/**"]
locales_exclude = ["Legacy/**"]Available exclude options:
src_excludelocales_exclude
- Dynamic namespaces in
useTranslation(...)are ignored. - Imported cross-file constants and functions are not fully resolved.
- Analysis is primarily intra-file.
- Only
.jsonlocale files are supported. - Only JavaScript and TypeScript source files are supported.