Generate translations for locales via built-in Java functionality (#29125)

Closes #29124

Signed-off-by: Jon Koops <jonkoops@gmail.com>
Signed-off-by: Alexander Schwartz <aschwart@redhat.com>
Co-authored-by: Jon Koops <jonkoops@gmail.com>
This commit is contained in:
Alexander Schwartz 2024-05-06 09:30:14 +02:00 committed by GitHub
parent c6d3e56cda
commit a9532274e3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
48 changed files with 106 additions and 555 deletions

View file

@ -1,3 +1,10 @@
import {
UserProfileFields,
beerify,
debeerify,
setUserProfileServerError,
useAlerts,
} from "@keycloak/keycloak-ui-shared";
import {
ActionGroup,
Alert,
@ -11,13 +18,6 @@ import { TFunction } from "i18next";
import { useState } from "react";
import { ErrorOption, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import {
UserProfileFields,
beerify,
debeerify,
setUserProfileServerError,
useAlerts,
} from "@keycloak/keycloak-ui-shared";
import {
getPersonalInfo,
@ -29,6 +29,7 @@ import {
UserRepresentation,
} from "../api/representations";
import { Page } from "../components/page/Page";
import { environment } from "../environment";
import { TFuncKey, i18n } from "../i18n";
import { useEnvironment } from "../root/KeycloakContext";
import { usePromise } from "../utils/usePromise";
@ -105,6 +106,7 @@ export const PersonalInfo = () => {
form={form}
userProfileMetadata={userProfileMetadata}
supportedLocales={supportedLocales}
currentLocale={environment.locale}
t={
((key: unknown, params) =>
t(key as TFuncKey, params as any)) as TFunction

View file

@ -2,6 +2,13 @@ import type GroupRepresentation from "@keycloak/keycloak-admin-client/lib/defs/g
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
import { UserProfileMetadata } from "@keycloak/keycloak-admin-client/lib/defs/userProfileMetadata";
import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation";
import {
FormErrorText,
HelpItem,
SwitchControl,
TextControl,
UserProfileFields,
} from "@keycloak/keycloak-ui-shared";
import {
ActionGroup,
AlertVariant,
@ -19,13 +26,6 @@ import { useEffect, useState } from "react";
import { Controller, FormProvider, UseFormReturn } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
import {
FormErrorText,
HelpItem,
SwitchControl,
TextControl,
UserProfileFields,
} from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../admin-client";
import { DefaultSwitchControl } from "../components/SwitchControl";
@ -33,6 +33,7 @@ import { useAlerts } from "../components/alert/Alerts";
import { FormAccess } from "../components/form/FormAccess";
import { GroupPickerDialog } from "../components/group/GroupPickerDialog";
import { useAccess } from "../context/access/Access";
import { useWhoAmI } from "../context/whoami/WhoAmI";
import { emailRegexPattern } from "../util";
import useFormatDate from "../utils/useFormatDate";
import { FederatedUserLink } from "./FederatedUserLink";
@ -73,6 +74,8 @@ export const UserForm = ({
const { hasAccess } = useAccess();
const isManager = hasAccess("manage-users");
const canViewFederationLink = hasAccess("view-realm");
const { whoAmI } = useWhoAmI();
const currentLocale = whoAmI.getLocale();
const {
handleSubmit,
@ -210,6 +213,7 @@ export const UserForm = ({
userProfileMetadata={userProfileMetadata}
hideReadOnly={!user}
supportedLocales={realm.supportedLocales || []}
currentLocale={currentLocale}
t={
((key: unknown, params) =>
t(key as string, params as any)) as TFunction

View file

@ -173,7 +173,9 @@ export const generateId = () => Math.floor(Math.random() * 1000);
export const localeToDisplayName = (locale: string, displayLocale: string) => {
try {
return new Intl.DisplayNames([displayLocale], { type: "language" }).of(
locale,
// This is mapping old locale codes to the new locale codes for Simplified and Traditional Chinese.
// Once the existing locales have been moved, this code can be removed.
locale === "zh-CN" ? "zh-HANS" : locale === "zh-TW" ? "zh-HANT" : locale,
);
} catch (error) {
return locale;

View file

@ -1,4 +1,5 @@
import { FormProvider } from "react-hook-form";
import { useMemo } from "react";
import { SelectControl } from "../controls/SelectControl";
import { UserProfileFieldProps } from "./UserProfileFields";
@ -12,17 +13,26 @@ const localeToDisplayName = (locale: string) => {
type LocaleSelectorProps = Omit<UserProfileFieldProps, "inputType"> & {
supportedLocales: string[];
currentLocale: string;
};
export const LocaleSelector = ({
t,
form,
supportedLocales,
currentLocale,
}: LocaleSelectorProps) => {
const locales = supportedLocales.map((locale) => ({
const locales = useMemo(
() =>
supportedLocales
.map((locale) => ({
key: locale,
value: localeToDisplayName(locale) || "",
}));
value: t(`locale_${locale}`, localeToDisplayName(locale) ?? locale),
}))
.sort((a, b) => a.value.localeCompare(b.value, currentLocale)),
[supportedLocales, currentLocale, t],
);
if (!locales.length) {
return null;
}

View file

@ -82,6 +82,7 @@ export type UserProfileFieldsProps = {
form: UseFormReturn<UserFormFields>;
userProfileMetadata: UserProfileMetadata;
supportedLocales: string[];
currentLocale: string;
hideReadOnly?: boolean;
renderer?: (
attribute: UserProfileAttributeMetadata,
@ -98,6 +99,7 @@ export const UserProfileFields = ({
form,
userProfileMetadata,
supportedLocales,
currentLocale,
hideReadOnly = false,
renderer,
}: UserProfileFieldsProps) => {
@ -153,6 +155,7 @@ export const UserProfileFields = ({
t={t}
form={form}
supportedLocales={supportedLocales}
currentLocale={currentLocale}
renderer={renderer}
attribute={attribute}
/>
@ -168,6 +171,7 @@ type FormFieldProps = {
t: TFunction;
form: UseFormReturn<UserFormFields>;
supportedLocales: string[];
currentLocale: string;
attribute: UserProfileAttributeMetadata;
renderer?: (
attribute: UserProfileAttributeMetadata,
@ -179,6 +183,7 @@ const FormField = ({
form,
renderer,
supportedLocales,
currentLocale,
attribute,
}: FormFieldProps) => {
const value = form.watch(
@ -196,6 +201,7 @@ const FormField = ({
<LocaleSelector
form={form}
supportedLocales={supportedLocales}
currentLocale={currentLocale}
t={t}
attribute={attribute}
/>

View file

@ -35,10 +35,13 @@ import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.keycloak.common.Profile;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import org.keycloak.services.util.LocaleUtil;
/**
@ -266,6 +269,7 @@ public class DefaultThemeManager implements ThemeManager {
}
}
addlocaleTranslations(locale, currentMessages);
this.messages.putIfAbsent(baseBundlename, new ConcurrentHashMap<>());
this.messages.get(baseBundlename).putIfAbsent(locale, groupedMessages);
@ -276,6 +280,53 @@ public class DefaultThemeManager implements ThemeManager {
}
}
protected void addlocaleTranslations(Locale locale, Properties m) throws IOException {
for (String l : getProperties().getProperty("locales", "").split(",")) {
l = l.trim();
String key = "locale_" + l;
String label = m.getProperty(key);
if (label != null) {
continue;
}
String rl = l;
// This is mapping old locale codes to the new locale codes for Simplified and Traditional Chinese.
// Once the existing locales have been moved, this code can be removed.
if (l.equals("zh-CN")) {
rl = "zh-HANS";
} else if (l.equals("zh-TW")) {
rl = "zh-HANT";
}
Locale loc = Locale.forLanguageTag(rl);
label = capitalize(loc.getDisplayName(locale), locale);
if (!Objects.equals(loc, locale)) {
label += " (" + capitalize(loc.getDisplayName(loc), loc) + ")";
}
m.put(key, label);
}
}
private static final Pattern LATIN_CHARACTERS;
static {
Pattern p;
try {
p = Pattern.compile("(\\p{L1}|\\p{InLATIN_EXTENDED_A}|\\p{InLATIN_EXTENDED_B}|\\p{InLATIN_EXTENDED_C}|\\p{InLATIN_EXTENDED_D}|\\p{InLATIN_EXTENDED_E}).*");
} catch (PatternSyntaxException ex) {
log.warn("unable to create regex for latin characters", ex);
// just in case the JVM doesn't recognize the language patterns used above
p = Pattern.compile("[a-zA-Z]");
}
LATIN_CHARACTERS = p;
}
private String capitalize(String name, Locale locale) {
if (LATIN_CHARACTERS.matcher(name).matches()) {
return name.substring(0, 1).toUpperCase(locale) + name.substring(1);
} else {
return name;
}
}
@Override
public Properties getProperties() throws IOException {
if (properties == null) {

View file

@ -20,6 +20,7 @@ package org.keycloak.theme.beans;
import org.keycloak.models.RealmModel;
import jakarta.ws.rs.core.UriBuilder;
import java.text.Collator;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;
@ -37,12 +38,16 @@ public class LocaleBean {
this.currentLanguageTag = current.toLanguageTag();
this.current = messages.getProperty("locale_" + this.currentLanguageTag, this.currentLanguageTag);
Collator collator = Collator.getInstance(current);
collator.setStrength(Collator.PRIMARY); // ignore case and accents
supported = realm.getSupportedLocalesStream()
.map(l -> {
String label = messages.getProperty("locale_" + l, l);
String url = uriBuilder.replaceQueryParam("kc_locale", l).build().toString();
return new Locale(l, label, url);
})
.sorted((o1, o2) -> collator.compare(o1.label, o2.label))
.collect(Collectors.toList());
}

View file

@ -56,7 +56,7 @@ public abstract class LanguageComboboxAwarePage extends AbstractPage {
}
public void openLanguage(String language){
WebElement langLink = localeDropdown.findElement(By.xpath("//a[text()='" + language + "']"));
WebElement langLink = localeDropdown.findElement(By.xpath("//a[text()[contains(.,'" + language + "')]]"));
String url = langLink.getAttribute("href");
DroneUtils.getCurrentDriver().navigate().to(url);
WaitUtils.waitForPageToLoad();

View file

@ -223,7 +223,7 @@ public class UncaughtErrorPageTest extends AbstractKeycloakTest {
try {
checkPageNotFound("/auth/realms/master/nosuch");
String url = driver.findElement(By.xpath("//a[text()='Deutsch']")).getAttribute("href");
String url = driver.findElement(By.xpath("//a[text()[contains(.,'Deutsch')]]")).getAttribute("href");
driver.navigate().to(url);
errorPage.assertCurrent();
} finally {

View file

@ -267,29 +267,6 @@ havePermissionRequestsWaitingForApproval=لديك {0} طلبات إذن في ا
clickHereForDetails=انقر هنا للتفاصيل.
resourceIsNotBeingShared=لم يتم مشاركة المورد
locale_ar=عربي
locale_ca=Català
locale_cs=Čeština
locale_de=Deutsch
locale_en=English
locale_es=Español
locale_fa=فارسی
locale_fr=Français
locale_hu=Magyar
locale_it=Italiano
locale_ja=日本語
locale_lt=Lietuvių
locale_nl=Nederlands
locale_no=Norsk
locale_pl=Polski
locale_pt-BR=Português (Brasil)
locale_ru=Русский
locale_sk=Slovenčina
locale_sv=Svenska
locale_tr=Türkçe
locale_zh-CN=中文简体
locale_fi=Suomi
# Applications
applicationName=الاسم
applicationType=نوع التطبيق

View file

@ -267,29 +267,6 @@ havePermissionRequestsWaitingForApproval=Teniu {0} peticions de permís esperant
clickHereForDetails=Feu clic aquí per a obtenir més detalls.
resourceIsNotBeingShared=El recurs no s''està compartint
locale_ar=àrab
locale_ca=català
locale_cs=txec
locale_de=alemany
locale_en=anglès
locale_es=castellà
locale_fr=francès
locale_hu=hongarès
locale_fa=persa
locale_it=italià
locale_ja=japonès
locale_lt=lituà
locale_nl=neerlandès
locale_no=noruec
locale_pl=polonès
locale_pt-BR=portuguès (Brasil)
locale_ru=rus
locale_sk=eslovè
locale_sv=suec
locale_tr=turc
locale_zh-CN=xinès simplificat
locale_fi=finès
# Applications
applicationName=Nom
applicationType=Tipus d''aplicació

View file

@ -168,5 +168,3 @@ invalidPasswordRegexPatternMessage=Neplatné heslo: neshoduje se zadaným regul
invalidPasswordHistoryMessage=Neplatné heslo: Nesmí se opakovat žádné z posledních {0} hesel.
invalidPasswordBlacklistedMessage=Neplatné heslo: heslo je na černé listině.
invalidPasswordGenericMessage=Neplatné heslo: nové heslo neodpovídá pravidlům hesla.
locale_fa=فارسی

View file

@ -226,23 +226,6 @@ permissionRequestion=Rettigsheds forespørgsel
permission=Tilladelse
shares=share(s)
locale_ca=Català
locale_de=Deutsch
locale_en=English
locale_es=Español
locale_fa=فارسی
locale_fr=Français
locale_it=Italian
locale_ja=日本語
locale_nl=Nederlands
locale_no=Norsk
locale_lt=Lietuvių
locale_pt-BR=Português (Brasil)
locale_ru=Русский
locale_sk=Slovenčina
locale_sv=Svenska
locale_zh-CN=中文简体
# Applications
applicationName=Navn
applicationType=Applikationstype

View file

@ -325,7 +325,6 @@ openshift.scope.user_info=Nutzerinformation
openshift.scope.user_check-access=Benutzerzugriffsinformationen
openshift.scope.user_full=Voller Zugriff
openshift.scope.list-projects=Projekte auflisten
locale_fa=فارسی
invalidPasswordMaxLengthMessage=Ungültiges Passwort: darf maximal {0} Zeichen beinhalten.
accountManagementBaseThemeCannotBeUsedDirectly=Das base Account Theme enthält nur Übersetzungen für die Account Console. Um die Account Console anzuzeigen, müssen Sie entweder das übergeordnete Theme auf ein anderes Account Theme setzen oder Ihre eigene index.ftl-Datei bereitstellen. Weitere Informationen entnehmen Sie bitte der Dokumentation.
role_view-groups=Zeige Gruppen

View file

@ -84,32 +84,11 @@ totpAppMicrosoftAuthenticatorName=Microsoft Authenticator
invalidEmailMessage=Μη έγκυρη διεύθυνση email.
accountDisabledMessage=Ο λογαριασμός έχει απενεργοποιηθεί, επικοινωνήστε με το διαχειριστή.
consentDenied=Άρνηση Συναίνεσης.
locale_ca=Català
locale_cs=Čeština
locale_de=Deutsch
locale_es=Español
locale_fr=Français
locale_hu=Magyar
locale_it=Italiano
locale_ja=日本語
locale_lt=Lietuvių
locale_nl=Nederlands
locale_no=Norsk
locale_pl=Polski
locale_pt-BR=Português (Brasil)
locale_ru=Русский
locale_sk=Slovenčina
locale_sv=Svenska
locale_tr=Türkçe
locale_zh-CN=中文简体
locale_fi=Suomi
doSave=Αποθήκευση
doCancel=Ακύρωση
doLogIn=Είσοδος
updatePasswordTitle=Ενημέρωση Κωδικού Πρόσβασης
locale_ar=عربي
authenticatorCode=Κωδικός μίας-χρήσης
locale_en=English
givenName=Όνομα
region=Νομός ή Περιφέρεια
fullName=Ονοματεπώνυμο

View file

@ -146,30 +146,6 @@ invalidPasswordNotUsernameMessage=Contraseña incorrecta: no puede ser igual al
invalidPasswordRegexPatternMessage=Contraseña incorrecta: no cumple la expresión regular.
invalidPasswordHistoryMessage=Contraseña incorrecta: no puede ser igual a ninguna de las últimas {0} contraseñas.
locale_ar=عربي
locale_ca=Català
locale_cs=Čeština
locale_de=Deutsch
locale_en=English
locale_es=Español
locale_fr=Français
locale_hu=Magyar
locale_fa=فارسی
locale_it=Italiano
locale_ja=日本語
locale_lt=Lietuvių
locale_nl=Nederlands
locale_no=Norsk
locale_pl=Polski
locale_pt-BR=Português (Brasil)
locale_ru=Русский
locale_sk=Slovenčina
locale_sv=Svenska
locale_th=ไทย
locale_tr=Türkçe
locale_zh-CN=中文简体
locale_fi=Suomi
doLogIn=Iniciar sesión
doLink=Enlace
noAccessMessage=Acceso no permitido

View file

@ -267,29 +267,6 @@ havePermissionRequestsWaitingForApproval=شما {0} درخواست مجوز در
clickHereForDetails=برای جزئیات اینجا را کلیک کنید.
resourceIsNotBeingShared=منبع به اشتراک گذاشته نمی شود
locale_ar=عربي
locale_ca=Català
locale_cs=Čeština
locale_de=Deutsch
locale_en=English
locale_es=Español
locale_fa=فارسی
locale_fr=Français
locale_hu=Magyar
locale_it=Italiano
locale_ja=日本語
locale_lt=Lietuvių
locale_nl=Nederlands
locale_no=Norsk
locale_pl=Polski
locale_pt-BR=Português (Brasil)
locale_ru=Русский
locale_sk=Slovenčina
locale_sv=Svenska
locale_tr=Türkçe
locale_zh-CN=中文简体
locale_fi=Suomi
# Applications
applicationName=نام
applicationType=نوع اپلیکیشن

View file

@ -256,26 +256,6 @@ noResourcesSharedWithYou=Kanssasi ei ole jaettuna resursseja
havePermissionRequestsWaitingForApproval=Sinulla on {0} lupapyyntöä odottamassa hyväksyntää.
clickHereForDetails=Klikkaa tästä nähdäksesi yksityiskohdat.
resourceIsNotBeingShared=Resurssia ei ole jaettu
locale_ca=Català
locale_de=Deutsch
locale_en=English
locale_es=Español
locale_fa=فارسی
locale_fr=Français
locale_hu=Magyar
locale_it=Italiano
locale_ja=日本語
locale_lt=Lietuvių
locale_nl=Nederlands
locale_no=Norsk
locale_pl=Polski
locale_pt-BR=Português (Brasil)
locale_ru=Русский
locale_sk=Slovenčina
locale_sv=Svenska
locale_tr=Türkçe
locale_zh-CN=中文简体
locale_fi=Suomi
# Applications
applicationName=Nimi

View file

@ -182,5 +182,3 @@ personalSubMessage=Gérez ces informations de base: votre prénom, nom de famill
accountSecurityIntroMessage=Gérez votre mot de passe et l''accès à votre compte
applicationsIntroMessage=Auditez et gérez les permissions d''accès des applications aux données de votre compte
applicationType=Type d''application
locale_fa=فارسی

View file

@ -267,29 +267,6 @@ havePermissionRequestsWaitingForApproval=Önnek {0} darab várakozó, jóváhagy
clickHereForDetails=Kattintson ide a részletekért.
resourceIsNotBeingShared=Az erőforrás nincs megosztva
locale_ar=عربي
locale_ca=Català
locale_cs=Čeština
locale_de=Deutsch
locale_en=English
locale_es=Español
locale_fr=Français
locale_hu=Magyar
locale_fa=فارسی
locale_it=Italiano
locale_ja=日本語
locale_lt=Lietuvių
locale_nl=Nederlands
locale_no=Norsk
locale_pl=Polski
locale_pt-BR=Português (Brasil)
locale_ru=Русский
locale_sk=Slovenčina
locale_sv=Svenska
locale_tr=Türkçe
locale_zh-CN=中文简体
locale_fi=Suomi
# Applications
applicationName=Név
applicationType=Alkalmazás típus

View file

@ -245,9 +245,6 @@ havePermissionRequestsWaitingForApproval=Hai {0} richiesta(e) di permesso in att
clickHereForDetails=Clicca qui per i dettagli.
resourceIsNotBeingShared=La risorsa non è in condivisione
locale_it=Italiano
locale_fa=فارسی
# Applications
applicationName=Nome
applicationType=Tipo applicazione

View file

@ -332,5 +332,3 @@ openshift.scope.user_info=ユーザー情報
openshift.scope.user_check-access=ユーザーアクセス情報
openshift.scope.user_full=フルアクセス
openshift.scope.list-projects=プロジェクトの一覧表示
locale_fa=فارسی

View file

@ -151,5 +151,3 @@ invalidPasswordMinSpecialCharsMessage=Neteisingas slaptažodis: privaloma įvest
invalidPasswordNotUsernameMessage=Neteisingas slaptažodis: slaptažodis negali sutapti su naudotojo vardu.
invalidPasswordRegexPatternMessage=Neteisingas slaptažodis: slaptažodis netenkina regex taisyklės(ių).
invalidPasswordHistoryMessage=Neteisingas slaptažodis: slaptažodis negali sutapti su prieš tai buvusiais {0} slaptažodžiais.
locale_fa=فارسی

View file

@ -166,24 +166,6 @@ permissionRequestion=Atļaujas pieprasījums
permission=Atļauja
shares=share(s)
locale_ca=Català
locale_de=Deutsch
locale_en=English
locale_es=Español
locale_fa=فارسی
locale_fr=Français
locale_it=Italian
locale_ja=日本語
locale_nl=Nederlands
locale_no=Norsk
locale_lt=Lietuvių
locale_lt=Latviešu
locale_pt-BR=Português (Brasil)
locale_ru=Русский
locale_sk=Slovenčina
locale_sv=Svenska
locale_zh-CN=中文简体
# Applications
applicationName=Nosaukums
applicationType=Lietojumprogrammas tips

View file

@ -340,4 +340,3 @@ error-invalid-date=Ongeldige datum.
error-user-attribute-read-only=Het veld {0} staat op alleen-lezen.
error-username-invalid-character=Gebruikersnaam bevat een ongeldig karakter.
error-person-name-invalid-character=Naam bevat een ongeldig karakter.
locale_fa=فارسی

View file

@ -150,5 +150,3 @@ invalidPasswordMinSpecialCharsMessage=Ugyldig passord: må inneholde minimum {0}
invalidPasswordNotUsernameMessage=Ugyldig passord: kan ikke være likt brukernavn.
invalidPasswordRegexPatternMessage=Ugyldig passord: tilfredsstiller ikke kravene for passord-mønster.
invalidPasswordHistoryMessage=Ugyldig passord: kan ikke være likt noen av de {0} foregående passordene.
locale_fa=فارسی

View file

@ -348,5 +348,3 @@ openshift.scope.user_info=Informações do usuário
openshift.scope.user_check-access=Informações de acesso do usuário
openshift.scope.user_full=Acesso Completo
openshift.scope.list-projects=Listar projetos
locale_fa=فارسی

View file

@ -232,5 +232,3 @@ invalidPasswordNotUsernameMessage=Некорректный пароль: пар
invalidPasswordRegexPatternMessage=Некорректный пароль: пароль не удовлетворяет регулярному выражению.
invalidPasswordHistoryMessage=Некорректный пароль: пароль не должен совпадать с последним(и) {0} паролями.
invalidPasswordGenericMessage=Некорректный пароль: новый пароль не соответствует правилам пароля.
locale_fa=فارسی

View file

@ -193,5 +193,3 @@ resourcesSharedWithMe=Zdroje zdieľané so mnou
permissionRequestion=Žiadosti o povolenie
permission=Oprávnenie
shares=podiel (y)
locale_fa=فارسی

View file

@ -147,5 +147,3 @@ invalidPasswordNotUsernameMessage=Ogiltigt lösenord: Får inte vara samma som a
invalidPasswordRegexPatternMessage=Ogiltigt lösenord: matchar inte kravet för lösenordsmönster.
invalidPasswordHistoryMessage=Ogiltigt lösenord: Får inte vara samma som de senaste {0} lösenorden.
invalidPasswordGenericMessage=Ogiltigt lösenord: Det nya lösenordet stämmer inte med lösenordspolicyn.
locale_fa=فارسی

View file

@ -313,5 +313,3 @@ addTeam=Kaynağınızı paylaşmak için ekip ekleyin
myPermissions=İzinlerim
waitingforApproval=Onay bekleniyor
anyPermission=Herhangi bir izin
locale_fa=فارسی

View file

@ -162,5 +162,3 @@ invalidPasswordMinSpecialCharsMessage=无效的密码: 至少包含 {0} 个特
invalidPasswordNotUsernameMessage=无效的密码: 不能与用户名相同
invalidPasswordRegexPatternMessage=无效的密码: 无法与正则表达式匹配
invalidPasswordHistoryMessage=无效的密码: 不能与之前的{0} 个旧密码相同
locale_fa=فارسی

View file

@ -272,33 +272,6 @@ havePermissionRequestsWaitingForApproval=您有 {0} 個權限請求等待批准
clickHereForDetails=點擊這裡查看詳細資訊。
resourceIsNotBeingShared=這個資源尚未被共享
locale_ar=عربي
locale_ca=Català
locale_cs=Čeština
locale_de=Deutsch
locale_en=English
locale_es=Español
locale_fr=Français
locale_hu=Magyar
locale_fa=فارسی
locale_it=Italiano
locale_ja=日本語
locale_lt=Lietuvių
locale_nl=Nederlands
locale_no=Norsk
locale_pl=Polski
locale_pt=Português
locale_pt-BR=Português (Brasil)
locale_ru=Русский
locale_sk=Slovenčina
locale_sv=Svenska
locale_th=ไทย
locale_tr=Türkçe
locale_uk=Українська
locale_zh-CN=中文简体
locale_zh-TW=繁體中文
locale_fi=Suomi
# Applications
applicationName=名稱
applicationType=應用程式型態

View file

@ -1 +1 @@
locales=ar,ca,cs,da,de,el,en,es,fa,fr,fi,hu,it,ja,lt,nl,no,pl,pt,pt-BR,ru,sk,sv,th,tr,uk,zh-CN,zh-TW
locales=ar,ca,cs,da,de,el,en,es,fa,fr,fi,hu,it,ja,lt,lv,nl,no,pl,pt,pt-BR,ru,sk,sv,th,tr,uk,zh-CN,zh-TW

View file

@ -357,30 +357,6 @@ confirmAccountLinking=Confirmeu l''enllaçat del compte {0} del proveïdor d''id
confirmEmailAddressVerification=Confirmeu la validesa de l''adreça de correu electrònic {0}.
confirmExecutionOfActions=Completeu les accions següents
locale_ar=àrab
locale_ca=català
locale_cs=txec
locale_da=danès
locale_de=alemany
locale_en=anglès
locale_es=castellà
locale_fi=finès
locale_fr=francès
locale_hu=hongarès
locale_it=italià
locale_ja=japonès
locale_lt=lituà
locale_lv=letó
locale_nl=neerlandès
locale_no=noruec
locale_pl=polonès
locale_pt_BR=portuguès (Brasil)
locale_ru=rus
locale_sk=eslovè
locale_sv=suec
locale_tr=turc
locale_zh-CN=xinès simplificat
backToApplication=&laquo; Torna a l''aplicació
missingParameterMessage=Manquen paràmetres\\: {0}
clientNotFoundMessage=No s''ha trobat el client.

View file

@ -361,31 +361,6 @@ confirmAccountLinking=Potvrďte propojení účtu {0} poskytovatele identity {1}
confirmEmailAddressVerification=Potvrďte platnost e-mailové adresy {0}.
confirmExecutionOfActions=Proveďte následující akce
#locale_ar=عربي
#locale_ca=Català
#locale_cs=Čeština
#locale_da=Dansk
#locale_de=Deutsch
#locale_en=English
#locale_es=Español
#locale_fi=Suomi
#locale_fr=Français
#locale_hu=Magyar
#locale_it=Italiano
#locale_ja=日本語
#locale_lt=Lietuvių
#locale_lv=Latviešu
#locale_nl=Nederlands
#locale_no=Norsk
#locale_pl=Polski
#locale_pt_BR=Português (Brasil)
#locale_ru=Русский
#locale_sk=Slovenčina
#locale_sv=Svenska
#locale_th=ไทย
#locale_tr=Türkçe
#locale_zh-CN=中文简体
backToApplication=&laquo; Zpět na aplikaci
missingParameterMessage=Chybějící parametry\: {0}
clientNotFoundMessage=Klient nebyl nalezen.

View file

@ -313,8 +313,6 @@ invalidUsernameOrEmailMessage=Ugyldigt brugernavn eller email.
invalidPasswordMessage=Ugyldig adangskode.
missingTotpDeviceNameMessage=Angiv venligst et udstyrsnavn.
nestedFirstBrokerFlowMessage={0} brugeren {1} er ikke forbundet til nogen kendt bruger.
locale_cs=Čeština
locale_pl=Polish
openshift.scope.user_info=Brugerinformation
openshift.scope.user_check-access=Brugeradgangsinformation
openshift.scope.user_full=Fuld adgang

View file

@ -318,30 +318,6 @@ identityProviderAlreadyLinkedMessage=Η ομόσπονδη ταυτότητα π
confirmAccountLinking=Επιβεβαιώστε τη σύνδεση του λογαριασμού {0} στο πάροχο ταυτότητας {1} με το λογαριασμό σας.
confirmEmailAddressVerification=Επιβεβαιώστε την εγκυρότητα της διεύθυνσης email {0}.
confirmExecutionOfActions=Πραγματοποιήστε την ακόλουθη ενέργεια(ες)
locale_ar=عربي
locale_ca=Català
locale_cs=Čeština
locale_da=Dansk
locale_de=Deutsch
locale_en=English
locale_es=Español
locale_fr=Français
locale_gr=Ελληνικά
locale_hu=Magyar
locale_it=Italiano
locale_ja=日本語
locale_lt=Lietuvių
locale_nl=Nederlands
locale_no=Norsk
locale_pl=Polski
locale_pt_BR=Português (Brasil)
locale_pt-BR=Português (Brasil)
locale_ru=Русский
locale_sk=Slovenčina
locale_sv=Svenska
locale_tr=Türkçe
locale_zh-CN=中文简体
locale_fi=Suomi
backToApplication=&laquo; Επιστροφή στην Εφαρμογή
missingParameterMessage=Λείπουν οι παράμετροι: {0}
clientNotFoundMessage=Ο πελάτης δε βρέθηκε.

View file

@ -410,31 +410,6 @@ identityProviderLinkSuccess=Verificó con éxito su correo electrónico. Vuelva
staleCodeMessage=Esta página ya no es válida, vuelva a su solicitud e inicie sesión nuevamente.
credentialSetupRequired=No se puede iniciar sesión, se requiere configuración de credencial.
locale_ar=عربي
locale_ca=Català
locale_cs=Čeština
locale_da=Dansk
locale_de=Deutsch
locale_en=English
locale_es=Español
locale_fi=Suomi
locale_fr=Français
locale_hu=Magyar
locale_it=Italiano
locale_ja=日本語
locale_lt=Lietuvių
locale_lv=Latviešu
locale_nl=Nederlands
locale_no=Norsk
locale_pl=Polski
locale_pt_BR=Português (Brasil)
locale_ru=Русский
locale_sk=Slovenčina
locale_sv=Svenska
locale_th=ไทย
locale_tr=Türkçe
locale_zh-CN=中文简体
clientDisabledMessage=Cliente deshabilitado.
differentUserAuthenticated=Ya está autenticado como un usuario diferente ''{0}'' en esta sesión. Por favor cierre sesión primero.
brokerLinkingSessionExpired=Vinculación de la cuenta del corredor solicitada, pero la sesión actual ya no es válida.

View file

@ -353,31 +353,6 @@ confirmAccountLinking=پیوند حساب {0} ارائه دهنده هویت {1}
confirmEmailAddressVerification=اعتبار آدرس ایمیل {0} را تأیید کنید.
confirmExecutionOfActions=عمل(های) زیر را انجام دهید
locale_ar=عربي
locale_ca=Català
locale_cs=Čeština
locale_da=Dansk
locale_de=Deutsch
locale_en=English
locale_es=Español
locale_fa=فارسی
locale_fi=Suomi
locale_fr=Français
locale_hu=Magyar
locale_it=Italiano
locale_ja=日本語
locale_lt=Lietuvių
locale_nl=Nederlands
locale_no=Norsk
locale_pl=Polski
locale_pt_BR=Português (Brasil)
locale_pt-BR=Português (Brasil)
locale_ru=Русский
locale_sk=Slovenčina
locale_sv=Svenska
locale_tr=Türkçe
locale_zh-CN=中文简体
backToApplication=&laquo; بازگشت به برنامه
missingParameterMessage=پارامترهای از دست رفته\: {0}
clientNotFoundMessage=مشتری یافت نشد

View file

@ -357,30 +357,6 @@ confirmAccountLinking=Erősítse meg a(z) {0} személyazonosság-kezelő {1} fi
confirmEmailAddressVerification=Erősítse meg a(z) {0} e-mail cím érvényességét.
confirmExecutionOfActions=Hajtsa végre a következő művelet(ek)et
locale_ar=عربي
locale_ca=Català
locale_cs=Čeština
locale_da=Dansk
locale_de=Deutsch
locale_en=English
locale_es=Español
locale_fi=Suomi
locale_fr=Français
locale_hu=Magyar
locale_it=Italiano
locale_ja=日本語
locale_lt=Lietuvių
locale_lv=Latviešu
locale_nl=Nederlands
locale_no=Norsk
locale_pl=Polski
locale_pt_BR=Português (Brasil)
locale_ru=Русский
locale_sk=Slovenčina
locale_sv=Svenska
locale_tr=Türkçe
locale_zh-CN=中文简体
backToApplication=&laquo; Vissza az alkalmazásba
missingParameterMessage=Hiányzó paraméterek\: {0}
clientNotFoundMessage=A kliens nem található.

View file

@ -275,7 +275,6 @@ identityProviderAlreadyLinkedMessage=L''identità federata restituita dall''iden
confirmAccountLinking=Conferma il collegamento per l''account {0} dell''identity provider {1} con il tuo account.
confirmEmailAddressVerification=Conferma la validità dell''indirizzo email {0}.
confirmExecutionOfActions=Esegui la/le seguenti azione/i
locale_it=Italiano
backToApplication=&laquo; Torna all''applicazione
missingParameterMessage=Parametri mancanti\: {0}

View file

@ -361,31 +361,6 @@ confirmAccountLinking=Potvrďte prepojenie účtu {0} poskytovateľa totožnosti
confirmEmailAddressVerification=Potvrďte platnosť e-mailovej adresy {0}.
confirmExecutionOfActions=Vykonajte nasledujúce akcie
#locale_ar=عربي
#locale_ca=Català
#locale_cs=Čeština
#locale_da=Dansk
#locale_de=Deutsch
#locale_en=English
#locale_es=Español
#locale_fi=Suomi
#locale_fr=Français
#locale_hu=Magyar
#locale_it=Italiano
#locale_ja=日本語
#locale_lt=Lietuvių
#locale_lv=Latviešu
#locale_nl=Nederlands
#locale_no=Norsk
#locale_pl=Polski
#locale_pt_BR=Português (Brasil)
#locale_ru=Русский
#locale_sk=Slovenčina
#locale_sv=Svenska
#locale_th=ไทย
#locale_tr=Türkçe
#locale_zh-CN=中文简体
backToApplication=&laquo; Späť na aplikáciu
missingParameterMessage=Chýbajúce parametre : {0}
clientNotFoundMessage=Klient sa nenašiel.

View file

@ -361,31 +361,6 @@ confirmAccountLinking=确认将身份提供者 {1} 的账户 {0} 与您的账户
confirmEmailAddressVerification=确认电子邮件地址 {0} 的有效性。
confirmExecutionOfActions=执行以下操作
locale_ar=عربي
locale_ca=Català
locale_cs=Čeština
locale_da=Dansk
locale_de=Deutsch
locale_en=English
locale_es=Español
locale_fi=Suomi
locale_fr=Français
locale_hu=Magyar
locale_it=Italiano
locale_ja=日本語
locale_lt=Lietuvių
locale_lv=Latviešu
locale_nl=Nederlands
locale_no=Norsk
locale_pl=Polski
locale_pt_BR=Português (Brasil)
locale_ru=Русский
locale_sk=Slovenčina
locale_sv=Svenska
locale_th=ไทย
locale_tr=Türkçe
locale_zh-CN=中文简体
backToApplication=&laquo; 回到应用
missingParameterMessage=缺少参数 \: {0}
clientNotFoundMessage=客户端未找到

View file

@ -365,34 +365,6 @@ confirmAccountLinking=確認連結身份提供者 {1} 的帳戶 {0} 至您的帳
confirmEmailAddressVerification=確認電子信箱 {0} 的有效性。
confirmExecutionOfActions=執行下列動作
locale_ar=عربي
locale_ca=Català
locale_cs=Čeština
locale_da=Dansk
locale_de=Deutsch
locale_en=English
locale_es=Español
locale_fi=Suomi
locale_fr=Français
locale_hu=Magyar
locale_it=Italiano
locale_ja=日本語
locale_lt=Lietuvių
locale_lv=Latviešu
locale_nl=Nederlands
locale_no=Norsk
locale_pl=Polski
locale_pt=Português
locale_pt_BR=Português (Brasil)
locale_ru=Русский
locale_sk=Slovenčina
locale_sv=Svenska
locale_th=ไทย
locale_tr=Türkçe
locale_uk=Українська
locale_zh-CN=中文简体
locale_zh-TW=繁體中文
backToApplication=&laquo; 返回應用程式
missingParameterMessage=遺失參數\: {0}
clientNotFoundMessage=找不到客戶端。

View file

@ -1 +1 @@
locales=ar,ca,cs,da,de,el,en,es,fa,fr,fi,hu,it,ja,lt,nl,no,pl,pt,pt-BR,ru,sk,sv,th,tr,uk,zh-CN,zh-TW
locales=ar,ca,cs,da,de,el,en,es,fa,fr,fi,hu,it,ja,lt,lv,nl,no,pl,pt,pt-BR,ru,sk,sv,th,tr,uk,zh-CN,zh-TW

View file

@ -272,33 +272,6 @@ havePermissionRequestsWaitingForApproval=You have {0} permission request(s) wait
clickHereForDetails=Click here for details.
resourceIsNotBeingShared=The resource is not being shared
locale_ar=عربي
locale_ca=Català
locale_cs=Čeština
locale_de=Deutsch
locale_en=English
locale_es=Español
locale_fr=Français
locale_hu=Magyar
locale_fa=فارسی
locale_it=Italiano
locale_ja=日本語
locale_lt=Lietuvių
locale_nl=Nederlands
locale_no=Norsk
locale_pl=Polski
locale_pt=Português
locale_pt-BR=Português (Brasil)
locale_ru=Русский
locale_sk=Slovenčina
locale_sv=Svenska
locale_th=ไทย
locale_tr=Türkçe
locale_uk=Українська
locale_zh-CN=中文简体
locale_zh-TW=繁體中文
locale_fi=Suomi
# Applications
applicationName=Name
applicationType=Application Type

View file

@ -371,34 +371,6 @@ confirmAccountLinking=Confirm linking the account {0} of identity provider {1} w
confirmEmailAddressVerification=Confirm validity of e-mail address {0}.
confirmExecutionOfActions=Perform the following action(s)
locale_ar=عربي
locale_ca=Català
locale_cs=Čeština
locale_da=Dansk
locale_de=Deutsch
locale_en=English
locale_es=Español
locale_fi=Suomi
locale_fr=Français
locale_hu=Magyar
locale_it=Italiano
locale_ja=日本語
locale_lt=Lietuvių
locale_lv=Latviešu
locale_nl=Nederlands
locale_no=Norsk
locale_pl=Polski
locale_pt=Português
locale_pt_BR=Português (Brasil)
locale_ru=Русский
locale_sk=Slovenčina
locale_sv=Svenska
locale_th=ไทย
locale_tr=Türkçe
locale_uk=Українська
locale_zh-CN=中文简体
locale_zh-TW=繁體中文
backToApplication=&laquo; Back to Application
missingParameterMessage=Missing parameters\: {0}
clientNotFoundMessage=Client not found.