本文へスキップ / Skip to main content
KINTO Tech Blog

6 min read

Localization

Managing Dynamic Placeholders in Multilingual Content: A Non-Developers Guide

Managing Dynamic Placeholders in Multilingual Content: A Non-Developers Guide cover
Speed
Read the summary

We solved a common problem in multilingual content: managing URLs and dates that shift position across languages. Without a clear system, teams waste time manually adjusting strings, leading to errors and delays. Our solution uses dynamic placeholders in strings, so the same base sentence can adapt to different languages. Instead of rewriting full sentences for each language, we keep one clean source string with placeholders like {terms} and {privacy}. This way, URLs are placed correctly in each language without extra work. We reduced internal rework from 5 reports per month to nearly zero. That means fewer QA back-and-forth sessions, faster releases, and better trust between localization and development teams. The system works with tools like Lokalise and GitHub, keeping translation data in sync with code. We built a simple JavaScript function called format() that replaces placeholders with actual URLs. It scans for {key} patterns and fills them with values from language-specific objects. For example, it turns “you agree to our {terms} and {privacy}” into the correct version in English or Japanese. The function handles all languages consistently, without needing to rewrite strings. This method saves time, reduces typos, and keeps content reusable. It shows that early design choices—like using clear, named placeholders—matter. As Microsoft says, internationalization should start from day one. Even if a product isn’t launched in another language yet, the right decisions today make future expansion easier.

This summary was generated by AI. Please refer to the article for accurate details.

Introduction

Handling variables like URLs, dates, or times in translatable sentences is a common challenge in localization. The position or format of these can vary significantly depending on the language, making it tricky to manage strings across languages, especially if you are managing multiple languages at the same time.
Hello! I’m Maya and I lead localization at KINTO Technologies. This article is for anyone managing multilingual content in-house in several languages without a coding background but would like to create a lean mechanism alongside their development colleagues. Don't worry if you're not familiar with coding; while having direct access to colleagues who can assist with implementation would be ideal, there are many resources available online to support you in managing your source language and translation data cohesively with your engineering team. In our case, we use Lokalise as our TMS and source of truth, integrated with GitHub to keep translation data and development in sync.

Why This Matters

For localization specialists, understanding how to use dynamic placeholders like URLs or dates can streamline your workflow and close the gap in communication between dev and localization teams. Shoutout to our teammate Wen-san for explaining this method in a beginner-friendly way!
In my case, since we implemented this approach, we’ve significantly reduced manual string adjustments, especially for placeholder-heavy sentences like terms and conditions and date/time formats. Internal rework due to these issues dropped from about 5 reports per month to nearly zero. We not only saved time but also minimized QA back-and-forth and improved trust between localization and development teams.

The Problem

Let’s take a sample sentence in English with two URLs:
"By using our service, you agree to our Terms and Conditions and Privacy Policy."
In Japanese, the URLs will be placed in a different position relative to the English one:
"本サービスを利用することにより、利用規約 および プライバシーポリシー に同意したものとみなされます。
If we had a third language, especially the more it differs from the above two, the position may again be different. If you’re handling multiple languages, managing these differences manually can be very time-consuming and error-prone.

The Solution: formatString()

Here’s where this function can be a lifesaver. It allows us to create a flexible template where the URLs can be placed dynamically, depending on the language. You can adjust the placement of the URLs in a sentence without having to rewrite the entire sentence for each language.
The tedious alternative many teams still face is hardcoding the URLs directly into each localized string, which leads to manually having to recreate near-identical sentence variants with cluttered string files, a higher risk of typos or broken links, and painful maintenance when URLs change.
This article introduces one solution to this issue using JavaScript as an example, but it can also be expressed in other programming languages such as Phython, C# or PHP.

Step 1: Identify the Dynamic Elements in Your Sentence

Let’s start with the previous sample sentence in English, our base language in this example:
"By using our service, you agree to our {Terms and Conditions} and {Privacy Policy}."
The placeholders {Terms and Conditions} and {Privacy Policy} represent URLs. While their content and placement will vary by language, they must remain clickable. Because sentence structures can differ across languages, these placeholders should be handled dynamically to fit each language's syntax.

Step 2: Create the Translatable String with Placeholders

In your i18n file in key-value format, you’ll define the placeholders that will be replaced by URLs. Using names ones instead of symbols ensures clarity and will prevent errors:
{
"terms_and_privacy": "By using our service, you agree to our {terms} and {privacy}."
}
Here I have renamed them simplified as {terms} and {privacy} to avoid issues in code. Best practice is to use simple, descriptive keys in snake_case or camelCase.

Step 3: Define the URLs and Anchor Texts Per Language

Now, define not just the URLs, but also the translated anchor texts. You’ll need to handle these separately for each language.
For English:
const en = {
terms: '<a href="https://example.com/terms_en">Terms and Conditions</a>',
privacy: '<a href="https://example.com/privacy_en">Privacy Policy</a>'
};
For Japanese:
const ja = {
terms: '<a href="https://example.com/terms_ja">利用規約</a>',
privacy: '<a href="https://example.com/privacy_ja">プライバシーポリシー</a>',
};

This gives flexibility, ensuring that both the anchor text and links are localized and reusable.

Step 4: Use the format() Function for Dynamic Replacement

Now comes the key step: using the format() method to replace the placeholders with the actual URLs.
While JavaScript doesn’t have a built-in method like some other languages such as Python, we can define our own formatting function to replace placeholders dynamically like this:

String.prototype.format = function (replacements) {
return this.replace(/{(\w+)}/g, (match, key) =>
typeof replacements[key] !== 'undefined' ? replacements[key] : match
);
};

// Example of localized string from i18n file
const localizedString = i18n.t('terms_and_privacy');

// Example for English
const formattedStringEn = localizedString.format(en);
console.log(formattedStringEn);
// Output: By using our service, you agree to our <a href="https://example.com/terms_en">Terms and Conditions</a> and <a href="https://example.com/privacy_en">Privacy Policy</a>.

// Example for Japanese
const formattedStringJa = localizedString.format(ja);
console.log(formattedStringJa);
// Output: 本サービスを利用することにより<a href="https://example.com/terms_ja">利用規約</a>および<a href="https://example.com/privacy_ja">プライバシーポリシー</a>に同意したものとみなされます。

The format() function searches for placeholders in curly braces, like {terms} or {privacy}, and replaces them with the corresponding values from the urls object.
Note for developers: you will see that I have inserted raw HTML into the strings, just for visual aid and demonstration purposes. In a production app, always sanitize them to prevent injection.

Final Thoughts

Combining placeholder-based translation strings with dynamic formatting gives you flexibility and control. It keeps your source clean and helps avoid many technical issues as well as human errors.
There are different placeholders, depending on the language, framework, or the type of argument they represent. While the Microsoft internationalization guidelines suggest giving translators control over placeholder naming, the key I think here is ensuring that developers and translators share a clear understanding of what each placeholder signifies.
To quote an example from their guidelines, to express Available Monday to Friday, from 8 AM to 5 PM Central Time, the first version will be easier to understand than the second one:
Available {firstWeekDay} to {lastWeekDay}, from {startTime} to {endTime} {timeZone}.
vs.
Available %s to %s, from %s to %s %s.
To wrap up, here’s a quote I like from Microsoft:
When working on any software project, it's important to think about internationalization from the very beginning of its design. Your first iteration or release may not be translated into another language, but the decisions that you make early in the project can determine your ability to deliver to other markets later. […] It's important to ensure all our features are world-ready.

Facebook

Follow Us

XConnpassWantedly

KINTOテクノロジーズの最新情報をSNSで発信中!イベント・テックブログ更新情報もお届けします。