Foundations
Formatting and localisation
Turkish is the source language and English the translation. Amounts, dates, numbers and lists are formatted with the browser's Intl API in each language; there is no hand-joined text and no hand-written format.
Languages
Section titled “Languages”- The interface has two languages: Turkish (
tr) and English (en). Turkish is the source; English text is translated from it (D-08). - English formats are pinned to the
en-GBlocale. A bareennever reaches Intl (I18N-15). - The language is chosen in this order: saved preference, the browser’s language header, Turkish. Changing language does not reload the page; route and form state are kept.
<html lang>shows the active language. A passage in another language carries its ownlang(I18N-14).- Right-to-left scripts are out of scope for this phase (I18N-24). Still, use logical CSS properties (
margin-inline-start,text-align: start).
Messages
Section titled “Messages”- Every text in the interface comes from a message id; there is no bare text in JSX. That includes
aria-label,altandplaceholder(I18N-06). - The design system’s own strings live in the
ui.*catalogue, such as Button’s loading text. Application strings take a four-part id:screen.section.element.purpose(I18N-02). - Do not build a sentence from pieces. Write a full sentence with variables:
{count, plural, one {# file selected} other {# files selected}}(I18N-07). - Turkish plural categories are
oneandother. In Turkish, a noun after a number stays singular: “3 dosya”. - Every message has a description: which screen, what the variables are, how many characters at most (I18N-03).
- Legal text is never kept in the message catalogue and never machine translated; it is published as a versioned document (D-08).
Format examples
Section titled “Format examples”The values below were produced with Intl when this page was built; the runtime gives the same output.
| Case | Turkish (tr-TR) | English (en-GB) | API |
|---|---|---|---|
| Amount | ₺1.234.567,89 | ₺1,234,567.89 | style: 'currency', currencyDisplay: 'narrowSymbol' |
| Negative amount | -₺1.234,50 | -₺1,234.50 | style: 'currency', currencyDisplay: 'narrowSymbol' |
| Zero amount | ₺0,00 | ₺0.00 | style: 'currency', currencyDisplay: 'narrowSymbol' |
| Percent | %12,3 | 12.3% | style: 'percent' |
| Number | 48.210,5 | 48,210.5 | Intl.NumberFormat |
| Short date | 25.10.2026 | 25/10/2026 | dateStyle: 'short' |
| Long date and time | 25 Ekim 2026 00:30 | 25 October 2026 at 00:30 | dateStyle: 'long', timeStyle: 'short' |
| Relative time | 3 gün önce | 3 days ago | Intl.RelativeTimeFormat |
| Yesterday | dün | yesterday | numeric: 'auto' |
| List | rapor, tablo ve grafik | report, table and chart | Intl.ListFormat |
| Upper case | İSTANBUL IŞIK | ISTANBUL | toLocaleUpperCase(locale) |
| Sorting | Ağaç, Ankara, Cam, Çilek, Şeker, Ürün, Zeytin | Ağaç, Ankara, Cam, Çilek, Şeker, Ürün, Zeytin | Intl.Collator(locale) |
Amounts
Section titled “Amounts”- Amounts are shown with a single
<Money>component, withnarrowSymbolin both languages: the ₺ sign, not “TRY” (I18N-10). - A Turkish lira amount always shows two decimals: “₺1,250.00”. An amount with zero kuruş keeps its decimals.
- The minus sign comes before the symbol: “-₺1,234.50”. Direction (incoming, outgoing) is also given by sign or text, not by colour alone.
- Amounts are not abbreviated (no “1.2M”); when they do not fit, they wrap. Abbreviation is only used on chart axes, with the full value in the tooltip.
- The front end never calculates fees or totals; amounts arrive calculated from the server. A missing value is not shown as “₺0.00”; it is handled as an error.
- Amount columns are right-aligned and use equal-width figures (
font-variant-numeric: tabular-nums). See Typography.
Numbers and percentages
Section titled “Numbers and percentages”- Numbers are formatted with
Intl.NumberFormat. Turkish uses a full stop for thousands and a comma for decimals; English the other way round. - In Turkish the percent sign comes before the number: “%12,3”. In English it comes after: “12.3%” (I18N-11).
- Long numbers such as ids and references are shown in groups of four for reading; when copied, they are copied without spaces.
Dates and times
Section titled “Dates and times”- Every date call carries
timeZone: 'Europe/Istanbul'; the device time zone is not used (I18N-12). - Time uses the 24-hour clock in both languages.
- Record, receipt and audit times are always absolute. Relative time such as “3 days ago” is only used in notification and activity feeds.
- In a date picker, closed days are explained in text as well as colour.
- Dates exchanged with the server are ISO 8601 with a time zone.
Upper case and sorting
Section titled “Upper case and sorting”- Upper case is done with
toLocaleUpperCase(locale);toUpperCase()converts the Turkish “i” wrongly (I18N-09). - Lists are sorted with
Intl.Collator(locale). The default.sort()puts Ç, Ğ, İ, Ö, Ş and Ü after Z (I18N-13). - Case-insensitive search follows Turkish rules: a search for “istanbul” finds “İstanbul”.
Text length
Section titled “Text length”- Build the interface for text that grows by 40 %. The pseudo-locale in Storybook lengthens text by 40 % and wraps it in brackets; broken layouts show up there (I18N-16, I18N-35).
- Do not give labels a fixed width or
white-space: nowrap. - Truncation is done only with the design system’s
Truncatecomponent; the full text stays in the accessible name and the tooltip. Amounts, references, dates, legal text and error text are never truncated.
Fonts and characters
Section titled “Fonts and characters”The brand font must cover Ç Ğ İ ı Ö Ş Ü and the ₺ sign (I18N-23). When a new brand font is added, these characters are checked during the build.
Guidelines
Section titled “Guidelines”Do not build sentences from pieces
Section titled “Do not build sentences from pieces”{count, plural, one {# file selected} other {# files selected}}count + " " + t("file") + " " + t("selected")Leave formatting to Intl
Section titled “Leave formatting to Intl”new Intl.NumberFormat(locale, options)value.toFixed(2).replace('.', ',')