# Internationalization (i18n) FolderWeb supports multilingual websites through the built-in `languages` plugin. This guide covers everything you need to build sites in multiple languages. ## How It Works The language plugin provides URL-based language selection: - **Default language:** `/about/` (no language prefix) - **Other languages:** `/no/om/`, `/de/uber-uns/` Language is determined from the URL, and content files, metadata, and translations adapt automatically. ## Configuration Enable and configure languages in `custom/config.ini`: ```ini [languages] default = "en" # Default language (no URL prefix) available = "en,no,de" # Comma-separated language codes [plugins] enabled = "languages" # Enable the language plugin ``` **Language codes:** Use ISO 639-1 two-letter codes (`en`, `no`, `de`, `fr`, `es`, etc.). ## Language-Specific Content Files Create language variants of content files using the naming pattern `name.lang.ext`: ``` content/about/ ├── index.md # Default language (English) ├── index.no.md # Norwegian version └── index.de.md # German version ``` **How it works:** - URL `/about/` → Shows `index.md` - URL `/no/om/` → Shows `index.no.md` - URL `/de/uber-uns/` → Shows `index.de.md` **Fallback behavior:** If no language-specific file exists, the default file is shown. ### Multiple Files Per Page Language variants work with multiple content files: ``` content/portfolio/ ├── 00-hero.php ├── 00-hero.no.php ├── 01-intro.md ├── 01-intro.no.md ├── 02-projects.html └── 02-projects.no.html ``` - URL `/portfolio/` → Shows `00-hero.php` + `01-intro.md` + `02-projects.html` - URL `/no/portfolio/` → Shows `00-hero.no.php` + `01-intro.no.md` + `02-projects.no.html` ## Language-Specific Metadata Override metadata fields for each language using sections in `metadata.ini`: ```ini # Default (English) title = "About Us" summary = "Learn about our company" slug = "about" # Norwegian [no] title = "Om oss" summary = "Les om bedriften vår" slug = "om" # German [de] title = "Über uns" summary = "Erfahren Sie mehr über unser Unternehmen" slug = "uber-uns" ``` **Supported fields:** - `title` — Page/item title - `summary` — Short description - `search_description` — SEO description - `slug` — Custom URL slug **Result:** - `/about/` — Title: "About Us" - `/no/om/` — Title: "Om oss" - `/de/uber-uns/` — Title: "Über uns" ## Translation Files UI strings (home link, footer text, month names) are translated using language files: ``` custom/languages/ ├── en.ini ├── no.ini └── de.ini ``` ### Creating Translation Files **custom/languages/en.ini:** ```ini home = "Home" footer_handcoded = "Generated in" footer_page_time = "ms" months = "January,February,March,April,May,June,July,August,September,October,November,December" ``` **custom/languages/no.ini:** ```ini home = "Hjem" footer_handcoded = "Generert på" footer_page_time = "ms" months = "januar,februar,mars,april,mai,juni,juli,august,september,oktober,november,desember" ``` **custom/languages/de.ini:** ```ini home = "Startseite" footer_handcoded = "Generiert in" footer_page_time = "ms" months = "Januar,Februar,März,April,Mai,Juni,Juli,August,September,Oktober,November,Dezember" ``` ### Using Translations in Templates Access translations via the `$translations` variable: ```php ``` ### Adding Custom Translation Strings Add any strings you need: **custom/languages/en.ini:** ```ini read_more = "Read more" posted_on = "Posted on" by_author = "by" categories = "Categories" tags = "Tags" ``` **custom/languages/no.ini:** ```ini read_more = "Les mer" posted_on = "Publisert" by_author = "av" categories = "Kategorier" tags = "Tagger" ``` Use in templates: ```php

``` ## Language Switcher The language plugin automatically provides language switcher URLs in the `$languageUrls` variable. **In base.php:** ```php 1): ?> ``` **How it works:** - The switcher links to the **same page** in different languages - Language-specific slugs are automatically resolved - Current language is marked with `aria-current="true"` **Example URLs:** - On `/about/`: EN → `/about/`, NO → `/no/om/`, DE → `/de/uber-uns/` - On `/no/om/`: EN → `/about/`, NO → `/no/om/`, DE → `/de/uber-uns/` ## Date Formatting Dates are automatically formatted using translated month names. **With `months` in language files:** ```ini # en.ini months = "January,February,March,April,May,June,July,August,September,October,November,December" # no.ini months = "januar,februar,mars,april,mai,juni,juli,august,september,oktober,november,desember" ``` **Result:** - English: "15. December 2024" - Norwegian: "15. desember 2024" **Date format:** `[day]. [month] [year]` (e.g., "15. December 2024") ## Complete Multilingual Example ### Directory Structure ``` content/ ├── metadata.ini ├── index.md ├── index.no.md └── blog/ ├── metadata.ini ├── 2024-12-15-first-post/ │ ├── metadata.ini │ ├── index.md │ ├── index.no.md │ └── cover.jpg └── 2024-12-20-second-post/ ├── metadata.ini ├── index.md └── index.no.md ``` ### Root Metadata **content/metadata.ini:** ```ini title = "My Site" [no] title = "Min Side" ``` ### Blog Metadata **content/blog/metadata.ini:** ```ini title = "Blog" summary = "Latest articles and updates" [no] title = "Blogg" summary = "Siste artikler og oppdateringer" ``` ### Post Metadata **content/blog/2024-12-15-first-post/metadata.ini:** ```ini title = "My First Post" summary = "An introduction to my blog" slug = "first-post" [no] title = "Mitt første innlegg" summary = "En introduksjon til bloggen min" slug = "forste-innlegg" ``` ### URLs Generated **English (default):** - Home: `/` - Blog: `/blog/` - Post: `/blog/first-post/` **Norwegian:** - Home: `/no/` - Blog: `/no/blogg/` - Post: `/no/blogg/forste-innlegg/` ## Language-Aware Navigation Navigation menus automatically use language-specific titles: **content/about/metadata.ini:** ```ini title = "About" menu = 1 menu_order = 10 [no] title = "Om" ``` **Result in navigation:** - English site: "About" - Norwegian site: "Om" ## Template Variables for i18n The language plugin provides these template variables: | Variable | Type | Description | |----------|------|-------------| | `$currentLang` | String | Current language code (e.g., `"en"`, `"no"`) | | `$defaultLang` | String | Default language from config | | `$langPrefix` | String | URL prefix (e.g., `""`, `"/no"`) | | `$languageUrls` | Array | URLs to switch languages | | `$translations` | Array | Translated UI strings | | `$availableLangs` | Array | All available language codes | **Example usage:** ```php ``` ## Right-to-Left (RTL) Languages For RTL languages (Arabic, Hebrew, etc.), set the `dir` attribute: **custom/templates/base.php:** ```php ``` Use logical CSS properties for proper RTL support: ```css /* Good: logical properties */ .card { margin-inline-start: 1rem; padding-inline-end: 2rem; } /* Bad: directional properties */ .card { margin-left: 1rem; padding-right: 2rem; } ``` ## Best Practices ### 1. Always Provide Fallbacks ```php ``` ### 2. Use Language Codes Consistently ```ini # Good [languages] available = "en,no,de" # Lowercase, ISO 639-1 # Bad available = "EN,nb-NO,de-DE" # Mixed case, non-standard ``` ### 3. Translate Everything Don't mix languages on the same page: ```php

Posted on

``` ### 4. Test All Languages Verify: - Content files load correctly - Metadata overrides work - Language switcher links are correct - Navigation uses translated titles - Dates format properly ### 5. Handle Missing Translations Gracefully ```php

``` ## Limitations ### No Automatic Translation FolderWeb doesn't translate content automatically. You must: - Create separate content files for each language - Manually translate all metadata - Provide all translation strings ### No Language Detection FolderWeb doesn't detect browser language. Users must: - Click the language switcher - Visit a language-specific URL directly You can add browser detection with a custom plugin if needed. ### Fixed URL Structure All languages share the same folder structure. You cannot have: - Content in `/en/blog/` and `/no/nyheter/` (different folder names) You must use: - Content in `/blog/` with language-specific slugs and content files ## Troubleshooting ### Language Switcher Shows Wrong URLs **Problem:** Language switcher links to incorrect pages. **Solution:** Check that language-specific slugs are set in metadata: ```ini slug = "about" [no] slug = "om" # Must be set ``` ### Content Not Changing Language **Problem:** Same content appears in all languages. **Solution:** Verify file naming: - ✓ `index.no.md` (correct) - ✗ `index-no.md` (wrong) - ✗ `index_no.md` (wrong) ### Dates Not Translating **Problem:** Dates show in English for all languages. **Solution:** Add `months` to language files: ```ini months = "January,February,March,April,May,June,July,August,September,October,November,December" ``` ### Navigation Shows English Titles **Problem:** Menu items use English even in other languages. **Solution:** Add language sections to metadata: ```ini title = "About" menu = 1 [no] title = "Om" ``` ## What's Next? - **[Configuration Reference](#)** — Configure available languages - **[Metadata Reference](#)** — Set language-specific metadata - **[Template Variables](#)** — Use i18n variables in templates - **[Creating Plugins](#)** — Extend i18n functionality