Skip to main content
Version: Next

I18N

local i18n = require("nauthilus_i18n")

The nauthilus_i18n module is a companion API for deployment-owned localization work. Final authentication responses should normally use auth.policy.policies[*].then.response_message.from: i18n plus optional response_language, because that keeps policy reports and HTTP, gRPC, and IdP rendering on one shared path.

Use this Lua module when a startup script needs to register deployment catalog overlays, or when request-time Lua needs localized text for Lua-owned logs, notices, or fallback strings.

nauthilus_i18n.get_localized

Resolves one stable localization key through the active effective catalog.

Syntax

local localized = i18n.get_localized({
i18n_key = "auth.policy.company.account_locked",
fallback = "Login failed because the account is locked.",
language = "de",
})

Parameters

The function accepts exactly one Lua table.

FieldRequiredMeaning
i18n_keyyesStable catalog key.
fallbackyesText returned when the key or selected language cannot be localized.
languagenoBCP 47 language tag. When omitted, Nauthilus uses the request's current language preference.

Returns

The function returns exactly one Lua table.

FieldMeaning
messageRendered localized message, or fallback text.
languageSelected language tag, when one was selected.
localizedtrue when a catalog entry was used.
i18n_keyRequested key.
fallback_usedtrue when fallback text was returned.

Example

local i18n = require("nauthilus_i18n")

local localized = i18n.get_localized({
i18n_key = "auth.policy.company.account_locked",
fallback = "Login failed because the account is locked.",
language = "en",
})

nauthilus_builtin.custom_log_add("localized_policy_message", localized.message)
nauthilus_builtin.custom_log_add("localized_policy_language", localized.language)

get_localized is read-only. It uses the same resolver semantics as policy response rendering: invalid or unsupported languages fall through to the next preference, missing translations return fallback, and maximum response-message length rules still apply.

nauthilus_i18n.register_catalog

Registers deployment-owned catalog entries during startup or init Lua execution.

Syntax

i18n.register_catalog({
language = "en",
namespace = "company",
entries = {
["auth.policy.company.account_locked"] = "Login failed because the account is locked.",
["auth.policy.company.account_unpaid"] = "Login failed because open payments exist and the account is locked.",
},
})

Parameters

The function accepts exactly one Lua table.

FieldRequiredMeaning
languageyesBCP 47 language tag for all entries in the table.
namespacenoDeployment namespace used in diagnostics and override logs.
entriesyesTable mapping stable i18n keys to localized strings.

Runtime Rules

  • register_catalog is available only during startup or init Lua execution.
  • Request-time Lua cannot mutate the active effective catalog.
  • Deployment overlays are merged after the system catalog in deterministic order.
  • Deployment overlays may add new keys and override system keys.
  • Overrides are logged with language, key, namespace, and previous namespace.
  • After startup succeeds, the effective catalog is frozen for request-time use.
  • On reload, Nauthilus builds and validates the next effective catalog first. The new catalog is activated atomically only after the reload succeeds. A failed reload keeps the previous catalog active.

Startup Example

Configure the init script as a Lua backend init script:

nauthilus.yml
auth:
backends:
lua:
backend:
default:
init_script_paths:
- /etc/nauthilus/policy/i18n.lua
/etc/nauthilus/policy/i18n.lua
local i18n = require("nauthilus_i18n")

i18n.register_catalog({
language = "en",
namespace = "company",
entries = {
["auth.policy.company.account_locked"] = "Login failed because the account is locked.",
["auth.policy.company.account_unpaid"] = "Login failed because open payments exist and the account is locked.",
},
})

The corresponding policy selects the key and fallback text:

auth:
policy:
policies:
- name: deny_company_locked_account
stage: auth_decision
operations: [authenticate]
if:
attribute: lua.company.account_status
eq: locked
then:
decision: deny
response_marker: auth.response.fail
response_message:
from: i18n
i18n_key: auth.policy.company.account_locked
fallback: "Login failed because the account is locked."

Do not add deployment example keys such as auth.policy.company.* to Nauthilus system resource files. Keep them in deployment-owned startup catalogs or external deployment material.

Testing and Mocks

Tests should use fake catalogs, fake resolvers, or fake startup catalog collectors. They do not need real Redis, LDAP, backend authentication, or production resource bundles.

Useful focused cases:

  • get_localized accepts exactly one table.
  • Missing i18n_key or fallback fails.
  • The return table contains message, language, localized, i18n_key, and fallback_used.
  • Missing keys return fallback text.
  • Invalid languages fall back through the resolver preference chain.
  • Deployment overlays override system keys.
  • Request-time Lua cannot call register_catalog.
  • Failed reload keeps the previous effective catalog active.