| name | localization |
| description | Use when implementing internationalization (i18n) or localization in SAP CAP: localized entities, _texts tables, i18n message bundles, @title annotations, locale-aware queries, translating UI labels, or working with @sap/cds/common Currency / Country / Language types.
|
| metadata | {"category":"cap","version":"1.0.0","keywords":["localized","i18n","_texts table","translation","CSV","message bundle","language","locale","multilingual"],"related":{"cds-modeling":"add localized elements to CDS entities","error-handling":"localized error messages","ui5-i18n":"UI5-side i18n for Fiori apps"}} |
Localization — CAP Best Practices
Primary reference: https://cap.cloud.sap/docs/guides/i18n
Localized data: https://cap.cloud.sap/docs/guides/localized-data
Localized entity elements
Mark translatable fields with localized:
entity Products : cuid {
localized title : String(111);
localized description : LargeString;
price : Decimal(9,2); // not localized — price is not translated
currency : Currency;
}
CAP auto-generates a Products_texts table with locale and ID keys. Translations are served automatically based on req.locale.
CSV for seed data (correct format since Nov 2025 docs update)
// db/data/my.namespace-Products.csv (comma-separated, not semicolons!)
ID,title,descr,price,currency_code
d4f1c8b2-...,Laptop,High performance laptop,999.99,EUR
// db/data/my.namespace-Products_texts.csv
ID,locale,title,descr
d4f1c8b2-...,de,Laptop,Hochleistungs-Laptop
d4f1c8b2-...,fr,Laptop,Ordinateur portable haute performance
Note: CAP documentation updated Nov 2025 — use comma-separated CSV, not semicolons.
i18n message bundles
Structure:
_i18n/
i18n.properties ← default (English)
i18n_de.properties ← German
i18n_fr.properties ← French
i18n_ja.properties ← Japanese
_i18n/i18n.properties:
# UI labels
Products=Products
Title=Title
Description=Description
Price=Price
# Error messages (with positional placeholders)
PRODUCT_NOT_FOUND=Product {0} was not found
INSUFFICIENT_STOCK=Insufficient stock: requested {0}, available {1}
ORDER_ALREADY_CLOSED=Order {0} is already closed and cannot be modified
_i18n/i18n_de.properties:
Products=Produkte
Title=Titel
Description=Beschreibung
PRODUCT_NOT_FOUND=Produkt {0} wurde nicht gefunden
INSUFFICIENT_STOCK=Nicht genügend Lagerbestand: angefordert {0}, verfügbar {1}
Using i18n keys in annotations
annotate Products with @(
title : '{i18n>Products}',
UI.LineItem : [
{ Value: title, Label: '{i18n>Title}' },
{ Value: price, Label: '{i18n>Price}' },
]
);
Using i18n keys in handlers (error messages)
req.reject(404, 'PRODUCT_NOT_FOUND', [productId])
req.reject(422, 'INSUFFICIENT_STOCK', [requested, available])
req.warn(200, 'ORDER_ALREADY_CLOSED', [orderId])
Currency, Country, Language reuse types
using { Currency, Country, Language } from '@sap/cds/common';
entity Products : cuid {
price : Decimal(9,2);
currency : Currency; // Association to sap.common.Currencies
origin : Country; // Association to sap.common.Countries
}
Seed pre-built content (currencies, countries, languages):
npm install @sap/cds-common-content --save-dev
{
"cds": {
"requires": {
"db": {
"model": ["@sap/cds-common-content", "db", "srv"]
}
}
}
}
Locale-aware querying
async onReadProducts(req) {
const { locale } = req
return SELECT.from(Products)
}
Manual locale override (rare):
const products = await SELECT.from(Products).where('...').localized(req.locale)
Temporal data (time-variant localization)
using { temporal } from '@sap/cds/common';
entity PriceHistory : cuid, temporal {
product : Association to Products;
price : Decimal(9,2);
currency : Currency;
}
temporal adds validFrom / validTo. CAP filters to the current period automatically.
Common mistakes to avoid
- ❌ Using semicolons in CSV data files — use commas (capire docs corrected this Nov 2025)
- ❌ Hardcoding translated strings in service handlers — always use
_i18n/ keys
- ❌ Defining Currency/Country as plain
String(3) — use the reuse types for value help & OData interop
- ❌ Forgetting
_texts CSV files — entity data loads but no translations show
- ❌ Using
@title: 'Products' (hardcoded) instead of @title: '{i18n>Products}' (translatable)
- ❌ Not adding the
@sap/cds-common-content model to cds.requires.db.model — currencies/countries empty