Hinzufügen lokalisierbarer Strings zu Themes und Theme-Komponenten

For those looking to add custom languages and translations to a Discourse theme or theme component, they can now include localised strings, which are made available for use in UI components. Translations are stored in the same format as core/plugin translations, and can be used in almost the same way.

Themes can supply translation files in a format like /locales/{locale}.yml. These files should be valid YAML, with a single top level key equal to the locale being defined. These can be defined using the discourse_theme CLI, importing a .tar.gz, installing from a GIT repository, or via the editor on theme-creator.discourse.org.

An example locale file might look like

en:
  theme_metadata:
    description: "This is a description for my theme"
    settings:
      theme_setting_name: "This is a description for the setting `theme_setting_name`"
      another_theme_setting_name:
        description: "This is a description for the setting `another_theme_setting_name`"
  sidebar:
    welcome: "Welcome"
    back: "back,"
    welcome_subhead: "We're glad you're here!"
    likes_header: "Share the Love"
    badges_header: "Your Top Badges"
    full_profile: "View your full profile"

Administrators can override individual keys on a per-theme basis in the /admin/customize/themes user interface. Fallback is handled in the same way as core, so it is ok to have incomplete translations for non-english languages will make use of the english keys.

In the background, these translations are stored alongside the core translations, under a theme-specific namespace. For example:

theme_translation.{theme_id}.sidebar.welcome

You should never hardcode the theme_id in your theme code, so there are a few ways to help you access the translations.

In .hbs files, you can use the dedicated helper

{{theme-i18n "my_translation_key"}}

Or, if you need to pass the translation key into another component, you can use the theme-prefix helper:

<DButton @label={{theme-prefix "my_translation_key"}} />

In Javascript, or in .gjs files, you can use the themePrefix function. This is automatically injected, and does not need to be imported:

const result = I18n.t(themePrefix("my_translation_key"));

<template>{{i18n (themePrefix "blah")}}</template>

For a complete example of using translations in a theme, check out @awesomerobot’s Fakebook theme: GitHub - discourse/Fakebook


This document is version controlled - suggest changes on github.

31 „Gefällt mir“

Howto use theme translations in CSS ? I know we can use theme parameters but I need theme translations.

You can’t, they’re only available in templates and javascript. That’s the same as core/plugin translations.

Ideally, refactor things so that the string is set in a template. But if you really need a customisable string in a css file, you could use theme settings: Developer’s guide to Discourse Themes

1 „Gefällt mir“

And if I use theme setting, is it possible to translate it ?

No, not in to multiple languages, but it would allow admins to customize it for their site.

2 „Gefällt mir“

Hello everyone.
I’m redefining the template upload-selector.hbs
I want to add a translatable phrase.
I created a new variable upload_selector.upload_images
For example

Please tell me what to do next?

Hello,

when i try this technic in the discourse theme creator (see here) everything works fine and as explained here in the post.

However if I import the very same theme on my own server only " [en.theme_translations.12.blog]" appears. Also in the theme settings page there is no “Theme Translations” section like on the theme creator.

I really don’t know where to search for this error anymore. Has anybody a hint for me?

[Edit]
I’m using discourse 2.6.7 ( [f73cdbbd2f ] ) in an docker environment.

can you update discourse ?

you are using an old version

Yeah i’m trying that, that is another thing i need help with but, I don’t want to post it here, that’s another topic.

Anyway I thought that shouldn’t be problem as the translation feature was included in version 2.2.0.beta9, see commit.

Hallo, entschuldigen Sie im Voraus für die Anfängerfrage.
Ich habe eine Kopfzeile nur mit HTML und CSS erstellt


        <div class="top-navbar">
         <span class="j_menu_item" ><a>Download</a></span>     
        </div>

Und dann möchte ich das Wort „Download“ übersetzen
Ich habe die englische Übersetzungsdatei erstellt

en: 
  top-navbar: 
    download: "Yeah"

Dann habe ich den HTML-Code wie im Facebook-Beispiel geändert


    <script type="text/x-handlebars" data-template-name="/connectors/discovery-below/sidebar">
        <div class="top-navbar">
         <a href="https://www.example.com/download">{{i18n (theme-prefix "top-navbar.download")}}</a></span>     
        </div>
    </script>

Dies übersetzt und gibt „Yeah“ aus, aber es ruiniert mein Layout. Ich vermute, es liegt daran, dass ich „/connectors/discovery-below/sidebar“ verwende. Ich möchte meine Übersetzung nur anwenden, ohne an einer Vorlage herumzufummeln, aber ich verstehe nicht, wie ich die Übersetzung einfach inline anwenden kann.

Könnten Sie bitte ein einfaches Beispiel geben, wie man eine Übersetzung im benutzerdefinierten HTML eines Themas verwendet?

Danke!

Hallo,

Das Problem ist, dass data-template-name ein eindeutiger Name sein sollte. Developing Discourse Themes & Theme Components. So: data-template-name=\"/connectors/PLUGIN-OUTLET-NAME/UNIQUE-NAME\" Jetzt verwenden Sie den Namen sidebar in Ihrem Beispiel, der meiner Meinung nach die Fakebook-Seitenleisten-Vorlage überschreibt.

Zum Beispiel sollte dies funktionieren :slightly_smiling_face:

<script type="text/x-handlebars" data-template-name="/connectors/discovery-below/downloadlink">
  <div class="top-navbar">
    <span class="j_menu_item" ><a href="https://www.example.com/download">{{i18n (theme-prefix "top-navbar.download")}}</a></span>     
  </div>
</script>
2 „Gefällt mir“

Danke @Don

Ich habe vergessen zu erwähnen, dass das Plugin nicht installiert ist und dass ich bereits versucht habe, den data-template-name in etwas Random UNIQUE-NAME zu ändern, mit demselben Ergebnis, oder dass mein Banner überhaupt nicht angezeigt wird, wenn ich mir den PLUGIN-OUTLET-NAME ausgedacht habe.
Sie können wahrscheinlich schon erkennen, dass ich mit Handlebars/Ember überhaupt nicht vertraut bin :slight_smile:
Mein Verständnis ist, dass ich eine Vorlage anpasse, die ihren vordefinierten Platz im HTML hat und das Ergebnis ist, dass der benutzerdefinierte HTML nicht mehr über /html/body/section main, sondern tief im Inneren liegt, was zu einer CSS-Vererbung führt, die ich vorher nicht hatte.
Was ich nicht verstehe, ist, warum ich eine Vorlage anpassen muss, um eine Übersetzung zu verwenden…
Ich konnte die anzupassende Vorlage mithilfe von Ember inspector identifizieren, wie hier empfohlen.
Und dank Ihrer Antwort und des Links zum Plugin-Outlet habe ich den richtigen data-template-name=“/connectors/above-site-header/my-navbar” gefunden.
Nochmals vielen Dank für Ihre Hilfe.

1 „Gefällt mir“

Ich verstehe… Ich dachte, Sie würden das Fakebook-Theme verwenden und Ihren Code unter dem Seitenleistenbereich platzieren wollen. :slightly_smiling_face:

Eine gute Möglichkeit, die Plugin-Outlets visuell zu sehen, ist die Verwendung der Plugin Outlet Locations Theme-Komponente.

2 „Gefällt mir“

Hallo @Don ,

Der Grund, warum ich dieses Facebook-Beispiel verwendet habe, ist:

Danke nochmals!

Was ist mit Singular und Plural, wie übersetzt man Text mit {{theme-i18n}}, wenn er eine und viele Übersetzungen hat? Zum Beispiel „Ergebnis“ und „Ergebnisse“.

2 „Gefällt mir“

Es gibt einige Beispiele dafür, wie wir dies in Discores Quellcode tun. Normalerweise haben wir zwei Zeichenfolgen und wechseln basierend auf einer Ganzzahl:

Screenshot 2022-12-15 um 17.42.58

Dies sollte auch in einem Theme funktionieren. Im Allgemeinen würde der JS-Code etwa so aussehen:

I18n.t(themePrefix("confirm_remove_tags"), {
  count: exampleCountValue,
});
1 „Gefällt mir“

und was ist mit hbs, kann das in hbs-Vorlagen gemacht werden?

1 „Gefällt mir“

Ja, das kann es:

{{theme-i18n "confirm_remove_tags" count=this.exampleCountValue}}
4 „Gefällt mir“

Wenn ich das in einer .gjs Component-Vorlage innerhalb eines Themes tue, erhalte ich:

Error: Attempted to resolve a helper in a strict mode template, but that value was not in scope: theme-prefix

Also versuche ich, es zu importieren:

import themePrefix from "discourse/helpers/theme-prefix";

Aber es murrt:

Identifier 'themePrefix' has already been declared

(Ich habe auf der 'Hub nach einem Beispiel gesucht, aber es scheint keines zu geben)

1 „Gefällt mir“

Update: Sie müssen {{i18n (themePrefix " verwenden

4 „Gefällt mir“