JavaScript
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Types
-
Section 3: Strings and Numbers in Depth
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Objects and Arrays
-
Section 7: Maps, Sets, and Symbols
-
Section 8: Asynchronous JavaScript
-
Section 9: Object-Oriented and Prototypes
-
Section 10: The DOM
-
Section 11: Browser APIs
-
Section 12: Modern JavaScript (ES2015-ES2025)
-
Section 13: Functional Programming Patterns
-
Section 14: Error Handling and Debugging
-
Section 15: Testing
-
Section 16: Accessibility for JavaScript Developers
-
Section 17: Internationalization and Localization
-
Section 18: Performance
-
Section 19: Node.js Fundamentals
-
Section 20: Regular Expressions
-
Section 21: Design Patterns in JavaScript
-
Section 22: Security Basics
-
Section 23: Data Structures and Algorithms in JavaScript
-
Section 24: Practical Projects
-
Section 25: More Advanced Async Patterns
-
Section 26: More Object and Class Practice
-
Section 27: Working with Dates and Internationalization
-
Section 28: Web Components
-
Section 29: More DOM and Browser Practice
-
Section 30: Build Tooling for Vanilla JavaScript
-
Section 31: More Practice Projects
-
Section 32: Interview and Algorithm Practice
-
Section 33: Error Objects (MDN Reference)
-
Section 34: TypedArrays and Binary Data
-
Section 35: Reflection and Metaprogramming (MDN Reference)
-
Section 36: More Global Functions (MDN Reference)
132: Structuring Translatable Strings
I've seen this mistake in almost every mid-sized project I've joined. A developer builds a great feature, and then the product manager says, "Great, now we need to launch in Spanish and Japanese." The developer looks at their code and realizes they've littered the entire codebase with template literals that are impossible to translate.
Here is a typical snippet of code that looks fine today, but will be a nightmare tomorrow:
function welcomeUser(user) {
const greeting = `Hello, ${user.name}! You have ${user.messages.length} unread messages.`;
return greeting;
}
The Fragility of Interpolated Sentences
At first glance, this is clean JS. But from a translation perspective, it's broken. You're assuming that every language follows the English word order: [Greeting], [Name]! You have [Number] [Adjective] [Noun].
In other languages, the word order shifts. The adjective might come after the noun, or the verb might move to the end of the sentence. If you hand this to a translator, they can't move the ${user.name} or ${user.messages.length} around because those are hardcoded into the logic of your JavaScript function. You'd have to rewrite your JS logic for every single language you support, which is a fast track to a codebase that is impossible to maintain.
Decoupling Content from Logic
The fix is to treat your strings as data, not as code. Instead of writing the sentence in your function, you use a "key" to look up the sentence in a translation file. We use placeholders (like {name}) that the translation engine can swap out regardless of where they appear in the sentence.
Here is how I would restructure that welcome message:
const translations = {
en: {
welcome_msg: "Hello, {name}! You have {count} unread messages.",
},
es: {
welcome_msg: "¡Hola, {name}! Tienes {count} mensajes sin leer.",
},
ja: {
welcome_msg: "{name}さん、こんにちは!未読メッセージが{count}件あります。",
}
};
function t(key, locale, variables = {}) {
let text = translations[locale][key];
// We replace the placeholders with the actual values
Object.keys(variables).forEach(varName => {
text = text.replace(`{${varName}}`, variables[varName]);
});
return text;
}
// Usage
const user = { name: "Alex", messages: [1, 2, 3] };
console.log(t('welcome_msg', 'en', { name: user.name, count: user.messages.length }));
console.log(t('welcome_msg', 'ja', { name: user.name, count: user.messages.length }));
Now, the JavaScript doesn't care about the sentence structure. The translator can move {name} to the end of the sentence in the ja (Japanese) object, and the code will still work perfectly. I've effectively separated the "what" (the data) from the "how" (the logic).
Handling the Pluralization Headache
If you stop there, you'll hit another wall: pluralization. In English, we have "1 message" and "2 messages." Some languages have three or more forms depending on the number. If you just append an "s" to the end of a word, your app will look amateurish in almost every language except English.
The professional way to handle this is to provide multiple keys for the same string based on a count. Instead of one welcome_msg, you might have welcome_msg_one and welcome_msg_other. Your translation function then checks the count and picks the correct key. It's slightly more work upfront, but it's the only way to ensure your UI feels native to the user.
📋 Practical Task
Build a Dynamic Shopping Cart Translator
You are building a shopping cart for an international store. You need to create a system that can handle different languages and correctly handle pluralization for the number of items in the cart.
Requirements:
- Create a
localesobject containing translations foren(English) andfr(French). - Include keys for
cart_empty,cart_single(for 1 item), andcart_multiple(for 2+ items). - Implement a function
getCartMessage(count, locale)that:- Returns the
cart_emptystring if the count is 0. - Returns the
cart_singlestring if the count is 1. - Returns the
cart_multiplestring if the count is 2 or more. - Correctly replaces a
{count}placeholder in the string with the actual number.
- Returns the
Example Expected Output:
getCartMessage(0, 'en'); // "Your cart is empty"
getCartMessage(1, 'en'); // "You have 1 item in your cart"
getCartMessage(5, 'en'); // "You have 5 items in your cart"
getCartMessage(5, 'fr'); // "Vous avez 5 articles dans votre panier"There are no comments for now.