add de translation, use []TagTranslation, and sort
to make sure the list of languages is sorted, we now use a slice of TagTranslation{Tag: string, Translation: string} structs, sorted by `TagTranslation.Tag`.
This commit is contained in:
parent
b9fe27b0ca
commit
7759e8f898
|
@ -152,8 +152,8 @@ func New(
|
|||
return func(postRoute *url.URL, classList string) template.HTML {
|
||||
languages := locHelper.ListLanguages()
|
||||
languageOptions := make([]string, len(languages))
|
||||
for tag, translation := range languages {
|
||||
languageOptions = append(languageOptions, createFormElement(postRoute.String(), tag, translation, classList))
|
||||
for _, entry := range languages {
|
||||
languageOptions = append(languageOptions, createFormElement(postRoute.String(), entry.Tag, entry.Translation, classList))
|
||||
}
|
||||
return (template.HTML)(strings.Join(languageOptions, "\n"))
|
||||
}
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
LanguageName = "Deutsch"
|
||||
|
||||
# generic terms
|
||||
GenericConfirm = "Ja"
|
||||
GenericGoBack = "Zurück"
|
||||
GenericSave = "Speichern"
|
||||
GenericCreate = "Erstellen"
|
||||
GenericSubmit = "Einreichen"
|
||||
GenericPreview = "Vorschau"
|
||||
GenericLanguage = "Sprache"
|
||||
GenericOpenLink = "Verbindung öffnen"
|
||||
|
||||
PageNotFound = "Die angeforderte Seite wurde nicht gefunden."
|
||||
|
||||
PubKeyRefPlaceholder = "@ .ed25519"
|
||||
|
||||
# roles
|
||||
RoleMember = "Mitglied"
|
||||
RoleModerator = "Moderator"
|
||||
RoleAdmin = "Administrator"
|
||||
|
||||
# navigation labels (should be single words or as short as possible)
|
||||
NavAdminLanding = "Zuhause"
|
||||
NavAdminDashboard = "Armaturenbrett"
|
||||
NavAdminInvites = "Einladungen"
|
||||
NavAdminNotices = "Hinweise"
|
||||
|
||||
# Error messages
|
||||
ErrorAuthBadLogin = "Die angegebenen Authentifizierungsdaten (Benutzername oder Passwort) sind falsch."
|
||||
ErrorNotFound = "Die Datenbank konnte den betreffenden Artikel nicht finden."
|
||||
ErrorAlreadyAdded = "Der öffentliche Schlüssel <strong> {{.Key}} </ strong> ist bereits in der Liste enthalten."
|
||||
ErrorPageNotFound = "Die angeforderte Seite <strong> ({{.Path}}) </ strong> ist nicht vorhanden."
|
||||
ErrorNotAuthorized = "Sie sind nicht autorisiert auf diese Seite zuzugreifen."
|
||||
ErrorForbidden = "Die Anforderung konnte wegen fehlender Berechtigungen ({{.Details}}) nicht ausgeführt werden."
|
||||
ErrorBadRequest = "Bei Ihrer Anfrage ist ein Problem aufgetreten: {{.Where}} ({{.Details}}"
|
||||
|
||||
# authentication
|
||||
################
|
||||
|
||||
AuthTitle = "Mitgliederauthentifizierung"
|
||||
AuthWelcome = "Wenn Sie Mitglied dieses Raums sind, können Sie auf das interne Dashboard zugreifen. Klicken Sie unten auf Ihre bevorzugte Anmeldemethode:"
|
||||
|
||||
AuthSignIn = "Einloggen"
|
||||
AuthSignOut = "Ausloggen"
|
||||
|
||||
# auth with ssb
|
||||
AuthWithSSBTitle = "Mit SSB anmelden"
|
||||
AuthWithSSBInstruct = "Einfache und sichere Methode, wenn Ihre SSB-App dies unterstützt."
|
||||
AuthWithSSBWelcome = "Um sich mit Ihrer auf diesem Gerät gespeicherten SSB-Identität anzumelden, drücken Sie die Taste unten, um eine kompatible SSB-App zu öffnen, falls diese installiert ist."
|
||||
AuthWithSSBInstructQR = "Wenn sich Ihre SSB-App auf einem anderen Gerät befindet, können Sie den folgenden QR-Code scannen, um sich mit der SSB-Identität dieses Geräts anzumelden."
|
||||
AuthWithSSBError = "Anmeldung fehlgeschlagen. Stellen Sie sicher, dass Sie eine SSB-App verwenden, die diese Anmeldemethode unterstützt, und klicken Sie innerhalb einer Minute nach dem Öffnen dieser Seite auf die Schaltfläche oben."
|
||||
|
||||
# auth with password
|
||||
AuthFallbackTitle = "Passwort anmelden"
|
||||
AuthFallbackWelcome = "Eine Anmeldung mit Benutzername und Passwort ist nur möglich, wenn der Administrator Ihnen eines gegeben hat, da wir die Benutzerregistrierung nicht unterstützen."
|
||||
AuthFallbackInstruct = "Diese Methode ist ein akzeptabler Fallback, wenn Sie einen Benutzernamen und ein Passwort haben."
|
||||
|
||||
# general dashboard stuff
|
||||
#########################
|
||||
|
||||
AdminDashboardTitle = "Armaturenbrett"
|
||||
AdminDashboardRoomID = "Der Ausweis dieses Zimmers lautet"
|
||||
|
||||
# privacy modes
|
||||
###############
|
||||
|
||||
ModeOpen = "Öffnen"
|
||||
ModeCommunity = "Gemeinschaft"
|
||||
ModeRestricted = "Eingeschränkt"
|
||||
|
||||
SetPrivacyModeTitle = "Datenschutzmodus einstellen"
|
||||
PrivacyModesTitle = "Datenschutzmodi"
|
||||
RoomsSpecification = "Zimmer 2 Spezifikation"
|
||||
ExplanationPrivacyModes = "Der Datenschutzmodus dieses Raums bestimmt, wer Einladungen erstellen und wer eine Verbindung zum Raum herstellen kann. Weitere Informationen finden Sie unter"
|
||||
ExplanationOpen = "Öffnen Sie Einladungscodes, jeder kann eine Verbindung herstellen"
|
||||
ExplanationCommunity = "Mitglieder können Einladungen erstellen, jeder kann eine Verbindung herstellen"
|
||||
ExplanationRestricted = "Nur Administratoren / Mods können Einladungen erstellen, nur Mitglieder dürfen eine Verbindung herstellen."
|
||||
|
||||
Settings = "Einstellungen"
|
||||
|
||||
DefaultLanguageTitle = "Voreinstellung"
|
||||
ExplanationDefaultLanguage = "Die Standard-Sprachoption steuert die Sprache der Raum-Weboberfläche, die für Erstbesucher angezeigt wird. Die verfügbaren Sprachoptionen werden durch die installierten Übersetzungsdateien definiert."
|
||||
SetDefaultLanguageTitle = "Voreinstellung ändern"
|
||||
|
||||
# banned dashboard
|
||||
##################
|
||||
|
||||
AdminDeniedKeysTitle = "Verboten"
|
||||
AdminDeniedKeysWelcome = "Auf dieser Seite können SSB-IDs gesperrt werden, damit sie nicht mehr auf den Raum zugreifen können."
|
||||
AdminDeniedKeysAdd = "Hinzufügen"
|
||||
AdminDeniedKeysAdded = "Schlüssel wurde zur Liste hinzugefügt."
|
||||
AdminDeniedKeysRemove = "Entfernen"
|
||||
AdminDeniedKeysComment = "Kommentar"
|
||||
AdminDeniedKeysCommentDescription = "Die Person, die dieses Verbot hinzugefügt hat, hat den folgenden Kommentar hinzugefügt"
|
||||
AdminDeniedKeysRemoveConfirmWelcome = "Sind Sie sicher, dass Sie dieses Verbot aufheben möchten? Sie werden wieder Zugang zum Raum haben."
|
||||
AdminDeniedKeysRemoveConfirmTitle = "Mitgliederentfernung bestätigen"
|
||||
|
||||
# members dashboard
|
||||
###################
|
||||
|
||||
AdminMembersTitle = "Mitglieder"
|
||||
AdminMembersWelcome = "Hier sehen Sie alle Mitglieder des Raums und Möglichkeiten, neue hinzuzufügen (anhand ihrer SSB-ID) oder vorhandene zu entfernen."
|
||||
AdminMembersAdd = "Hinzufügen"
|
||||
|
||||
AdminMembersRemoveConfirmTitle = "Mitgliederentfernung bestätigen"
|
||||
AdminMembersRemoveConfirmWelcome = "Sind Sie sicher, dass Sie dieses Mitglied entfernen möchten? Sie verlieren ihren Alias, wenn sie einen haben."
|
||||
|
||||
AdminMemberDetailsTitle = "Mitgliederdetails"
|
||||
AdminMemberDetailsSSBID = "SSB-Kennung"
|
||||
AdminMemberDetailsRole = "Berechtigungsstufe"
|
||||
AdminMemberDetailsAliases = "Aliase"
|
||||
AdminMemberDetailsAliasRevoke = "Widerrufen"
|
||||
AdminMemberDetailsAliasRevoked = "Alias wurde widerrufen"
|
||||
AdminMemberDetailsExclusion = "Ausschluss aus diesem Raum"
|
||||
AdminMemberDetailsRemove = "Mitglied entfernen"
|
||||
|
||||
AdminMemberAdded = "Mitglied erfolgreich hinzugefügt."
|
||||
AdminMemberUpdated = "Mitglied aktualisiert."
|
||||
AdminMemberRemoved = "Mitglied entfernt."
|
||||
|
||||
AdminAliasesRevoke = "Widerrufen"
|
||||
AdminAliasesRevokeConfirmTitle = "Alias widerrufen"
|
||||
AdminAliasesRevokeConfirmWelcome = "Sind Sie sicher, dass Sie diesen Alias widerrufen möchten?"
|
||||
|
||||
# invite dashboard
|
||||
##################
|
||||
|
||||
AdminInvitesTitle = "Einladungen"
|
||||
AdminInvitesWelcome = "Erstellen Sie Einladungs-Token für Personen, die noch keine Mitglieder dieses Raums sind. Auf dieser Seite sehen Sie auch zuvor erstellte Einladungen, die von neuen Mitgliedern noch nicht beansprucht werden."
|
||||
AdminInvitesCreate = "Neue Einladung erstellen"
|
||||
AdminInvitesCreatedAtColumn = "Hergestellt in"
|
||||
AdminInvitesCreatorColumn = "Erstellt von"
|
||||
AdminInvitesActionColumn = "Aktion"
|
||||
AdminInviteRevoke = "Widerrufen"
|
||||
|
||||
AdminInviteRevokeConfirmTitle = "Widerruf der Einladung bestätigen"
|
||||
AdminInviteRevokeConfirmWelcome = "Sind Sie sicher, dass Sie diese Einladung entfernen möchten? Wenn Sie sie bereits gesendet haben, können sie sie nicht verwenden."
|
||||
|
||||
# TODO: add placeholder support to the template helpers (https://github.com/ssb-ngi-pointer/go-ssb-room/issues/60)
|
||||
AdminInviteCreatedBy = "Erstellt von:"
|
||||
AdminInviteSuggestedAliasIs = "Der vorgeschlagene Alias lautet:"
|
||||
AdminInviteSuggestedAliasIsShort = "Alias:"
|
||||
|
||||
AdminInviteCreatedTitle = "Einladung erfolgreich erstellt!"
|
||||
AdminInviteCreatedInstruct = "Kopieren Sie nun den folgenden Link und fügen Sie ihn in einen Freund ein, den Sie in diesen Raum einladen möchten."
|
||||
|
||||
# public invites
|
||||
################
|
||||
|
||||
InviteFacade = "Raum betreten"
|
||||
InviteFacadeTitle = "Raum betreten"
|
||||
InviteFacadeWelcome = "Sie haben die Erlaubnis, Mitglied dieses Raums zu werden, weil jemand diese Einladung mit Ihnen geteilt hat."
|
||||
InviteFacadeInstruct = "Um die Einladung zu erhalten, klicken Sie auf die Schaltfläche unten, um eine kompatible SSB-App zu öffnen, falls diese installiert ist."
|
||||
InviteFacadeJoin = "Tritt diesem Raum bei"
|
||||
InviteFacadeWaiting = "SSB App öffnen"
|
||||
InviteFacadeInstructQR = "Wenn sich Ihre SSB-App auf einem anderen Gerät befindet, können Sie den folgenden QR-Code scannen, um Ihre Einladung auf diesem Gerät zu erhalten:"
|
||||
|
||||
InviteFacadeFallbackWelcome = "Sind Sie neu bei SSB? Es scheint, dass Sie keine SSB-App haben, die diesen Link verstehen kann. Sie können eine dieser Apps installieren:"
|
||||
InviteFacadeFallbackManyverse = "Installiere Manyverse"
|
||||
InviteFacadeFallbackInsertID = "SSB-ID einfügen"
|
||||
|
||||
InviteInsertWelcome = "Sie können Ihre Einladung anfordern, indem Sie unten Ihre SSB-ID eingeben. Danach können Sie in Ihrer SSB-App eine Verbindung zum Raum herstellen."
|
||||
|
||||
InviteConsumedTitle = "Einladung angenommen!"
|
||||
InviteConsumedWelcome = "Sie sind jetzt Mitglied dieses Raums. Wenn Sie eine Multiserver-Adresse benötigen, um eine Verbindung zum Raum herzustellen, können Sie die folgende kopieren und einfügen:"
|
||||
|
||||
# notices (mini-CMS)
|
||||
####################
|
||||
|
||||
NoticeEditTitle = "Hinweis bearbeiten"
|
||||
NoticeList = "Hinweise"
|
||||
NoticeListWelcome = "Hier können Sie den Inhalt der Zielseite und anderer wichtiger Dokumente wie Verhaltenskodex und Datenschutzbestimmungen verwalten."
|
||||
NoticeAddTranslation = "Hinzufügen"
|
||||
NoticeUpdated = "Hinweis aktualisiert"
|
||||
|
||||
NoticeCodeOfConduct = "Verhaltenskodex"
|
||||
NoticeNews = "Nachrichten"
|
||||
NoticeDescription = "Beschreibung"
|
||||
NoticePrivacyPolicy = "Datenschutz-Bestimmungen"
|
||||
|
||||
# Plurals
|
||||
#########
|
||||
# These need to use this form and get {{.Count}}
|
||||
# [Label]
|
||||
# one = singular
|
||||
# other = {{.Count}} things
|
||||
|
||||
[MemberCount]
|
||||
description = "Anzahl der Mitglieder"
|
||||
one = "1 Mitglied"
|
||||
other = "{{.Count}} Mitglieder"
|
||||
|
||||
[ListCount]
|
||||
description = "generische Liste"
|
||||
one = "Es gibt einen Punkt auf der Liste"
|
||||
other = "Die Liste enthält {{.Count}} Elemente"
|
||||
|
||||
[AdminRoomCount]
|
||||
description = "Die Anzahl der Personen in einem Raum"
|
||||
one = "Es ist eine Person im Raum"
|
||||
other = "Es sind {{.Count}} Personen im Raum"
|
||||
|
||||
[AdminInvitesCount]
|
||||
description = "die Anzahl der Einladungen, die noch nicht beansprucht wurden"
|
||||
one = "1 Einladung noch nicht beansprucht"
|
||||
other = "{{.Count}} lädt noch nicht beanspruchte ein"
|
|
@ -11,6 +11,7 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
|
@ -26,9 +27,14 @@ import (
|
|||
|
||||
const LanguageCookieName = "gossbroom-language"
|
||||
|
||||
type TagTranslation struct {
|
||||
Tag string
|
||||
Translation string
|
||||
}
|
||||
|
||||
type Helper struct {
|
||||
bundle *i18n.Bundle
|
||||
languages map[string]string
|
||||
languages []TagTranslation
|
||||
cookieStore *sessions.CookieStore
|
||||
config roomdb.RoomConfig
|
||||
}
|
||||
|
@ -139,38 +145,52 @@ func New(r repo.Interface, config roomdb.RoomConfig) (*Helper, error) {
|
|||
return &Helper{bundle: bundle, languages: langmap, cookieStore: cookieStore, config: config}, nil
|
||||
}
|
||||
|
||||
func listLanguages(bundle *i18n.Bundle) map[string]string {
|
||||
langmap := make(map[string]string)
|
||||
func listLanguages(bundle *i18n.Bundle) []TagTranslation {
|
||||
languageTags := bundle.LanguageTags()
|
||||
tags := make([]string, 0, len(languageTags))
|
||||
langslice := make([]TagTranslation, 0, len(languageTags))
|
||||
|
||||
for _, langTag := range bundle.LanguageTags() {
|
||||
// convert from i18n language tags to a slice of strings
|
||||
for _, langTag := range languageTags {
|
||||
tags = append(tags, langTag.String())
|
||||
}
|
||||
// sort the slice of language tag strings
|
||||
sort.Strings(tags)
|
||||
|
||||
// now that we have a known order, construct a TagTranslation slice mapping language tags to their translations
|
||||
for _, langTag := range tags {
|
||||
var l Localizer
|
||||
l.loc = i18n.NewLocalizer(bundle, langTag.String())
|
||||
l.loc = i18n.NewLocalizer(bundle, langTag)
|
||||
|
||||
msg, err := l.loc.Localize(&i18n.LocalizeConfig{
|
||||
MessageID: "LanguageName",
|
||||
})
|
||||
if err != nil {
|
||||
msg = langTag.String()
|
||||
msg = langTag
|
||||
}
|
||||
|
||||
langmap[langTag.String()] = msg
|
||||
langslice = append(langslice, TagTranslation{Tag: langTag, Translation: msg})
|
||||
}
|
||||
|
||||
return langmap
|
||||
return langslice
|
||||
}
|
||||
|
||||
// ListLanguages returns a map of the room's translated languages.
|
||||
// The map's keys are language tags (as strings) and the corresponding value is the translated language name.
|
||||
// Example: en -> English, sv -> Svenska, de -> Deutsch
|
||||
func (h Helper) ListLanguages() map[string]string {
|
||||
// ListLanguages returns a slice of the room's translated languages.
|
||||
// The entries of the slice are of the type TagTranslation, consisting of the fields Tag and Translation.
|
||||
// Each Tag fields is a language tag (as strings), and the field Translation is the corresponding translated language
|
||||
// name of that language tag.
|
||||
// Example: {Tag: en, Translation: English}, {Tag: sv, Translation: Svenska} {Tag: de, Translation: Deutsch}
|
||||
func (h Helper) ListLanguages() []TagTranslation {
|
||||
return h.languages
|
||||
}
|
||||
|
||||
func (h Helper) ChooseTranslation(tag string) string {
|
||||
if translation, ok := h.languages[tag]; ok {
|
||||
return translation
|
||||
func (h Helper) ChooseTranslation(requestedTag string) string {
|
||||
for _, entry := range h.languages {
|
||||
if entry.Tag == requestedTag {
|
||||
return entry.Translation
|
||||
}
|
||||
}
|
||||
return tag
|
||||
return requestedTag
|
||||
}
|
||||
|
||||
type Localizer struct {
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"github.com/ssb-ngi-pointer/go-ssb-room/web/i18n"
|
||||
)
|
||||
|
||||
func TestListAllLanguages(t *testing.T) {
|
||||
func TestListLanguages(t *testing.T) {
|
||||
configDB := new(mockdb.FakeRoomConfig)
|
||||
configDB.GetDefaultLanguageReturns("en", nil)
|
||||
r := repo.New(filepath.Join("testrun", t.Name()))
|
||||
|
@ -18,6 +18,6 @@ func TestListAllLanguages(t *testing.T) {
|
|||
helper, err := i18n.New(r, configDB)
|
||||
a.NoError(err)
|
||||
t.Log(helper)
|
||||
langmap := helper.ListLanguages()
|
||||
a.Equal(langmap["en"], "English")
|
||||
translation := helper.ChooseTranslation("en")
|
||||
a.Equal(translation, "English")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue