Skip to content

Rules and Guidelines

Localization & Internationalization

At Glow Up, we use i18next as our core internationalization library to support a seamless multilingual experience in our applications. i18next provides a comprehensive and flexible approach to handling translations, pluralizations, and variable replacements, making it a vital part of our design and development process.

Escaping & Security

Preventing XSS Attacks

By default, i18next escapes special characters to prevent Cross-Site Scripting (XSS) attacks. This ensures that user-generated content does not introduce security vulnerabilities.

Security Best Practices

Always validate and sanitize any dynamic content that comes from external sources. While i18next provides basic escaping, additional security measures may be required for highly dynamic applications.

Fallback Strategy

Fallback Language Configuration

When a translation key is not available in the current language, i18next will use a fallback language. At Glow Up, we use en_US as our default fallback language.

Naming Conventions

Use snake_case for Keys

All translation keys should use snake_case to ensure consistency across the codebase and make it easier to read and maintain.

Example: login_button_label instead of loginButtonLabel or LoginButtonLabel.

Keep Keys Descriptive but Short

Keys should be descriptive enough to understand their purpose but not excessively long. Strive for a balance that clearly indicates the context without being overly verbose.

Example: user_profile_update_success is clear, but avoid overly detailed keys like user_profile_update_success_message_shown.

Variable Naming

Use Clear and Consistent Variable Names

Variables embedded in translation strings should be named clearly and consistently, using braces {} to denote them.

Example:

{
"welcome_message": "Welcome, {username}!",
"items_in_cart": "You have {count} items in your cart."
}

Formatting Dates, Numbers, and Currencies

Using Intl with i18next

To format dates, numbers, and currencies consistently, use the JavaScript Intl API in combination with i18next. This ensures that formatting is accurate and localized for each language.

Example:

const formattedDate = new Intl.DateTimeFormat(i18n.language).format(new Date());
const formattedNumber = new Intl.NumberFormat(i18n.language, {
style: 'currency',
currency: 'USD'
}).format(12345.67);

Handling Plurals

Use one and other for Plurals

When dealing with pluralization, use one and other to specify the correct forms in different languages. This ensures that the translation adapts correctly to the quantity.

Example:

{
"welcome_message": "Bienvenue, {username}!",
"items_in_cart": "Vous avez {count} articles dans votre panier."
}

Structuring Translation Keys

Organize related translation keys under a common namespace to keep the structure clean and manageable.

Example:

{
"profile": {
"edit": "Edit Profile",
"settings": "Profile Settings"
},
"notifications": {
"new_message": "You have a new message."
}
}

Why Group Keys?

=======

Descriptive Keys

Always use descriptive keys that clearly convey the purpose of the translation. Avoid generic names like label1 or text2, which make it difficult to understand the context or purpose of the string.

Good Example:

{
"profile": {
"edit_button": "Edit Profile",
"logout_button": "Log Out"
}
}

Handling Contextual Translations

Using Context with i18next

i18next allows you to provide different translations based on context, which is helpful for words that have multiple meanings depending on usage.

Example:

{
"button": {
"save": "Save",
"save_female": "Save (Female)"
}
}

Usage in Svelte:

i18n.t('button.save', { context: 'female' });

Fallback Keys and Debugging

Handling Missing Keys

If a translation key is missing, i18next can provide useful debugging information. You can configure it to log warnings or provide fallback keys for easier troubleshooting.

Example Configuration:

i18n.init({
debug: true, // Enable debugging
missingKeyHandler: function (lng, ns, key) {
console.warn(`Missing translation key: ${key}`);
}
});