From 7c42cd8a652d67b86ffa11b6c678ef5964906fb5 Mon Sep 17 00:00:00 2001 From: Yaodong Li Date: Thu, 13 Jul 2023 13:22:54 +0800 Subject: [PATCH 1/3] feat: add zh translation --- frontend/elements/README.md | 274 ++++++++++++++------------- frontend/elements/package.json | 28 ++- frontend/elements/src/i18n/all.ts | 3 +- frontend/elements/src/i18n/zh.ts | 110 +++++++++++ frontend/elements/webpack.config.cjs | 67 +++---- 5 files changed, 312 insertions(+), 170 deletions(-) create mode 100644 frontend/elements/src/i18n/zh.ts diff --git a/frontend/elements/README.md b/frontend/elements/README.md index b08f70744..d8ae6b7be 100644 --- a/frontend/elements/README.md +++ b/frontend/elements/README.md @@ -38,20 +38,20 @@ that provides the underlying functionalities. ## Features -* User Authentication: Provides a secure and user-friendly way to handle user authentication within web applications. -* Authentication Flows: Supports various authentication flows, including passwordless authentication and biometric +- User Authentication: Provides a secure and user-friendly way to handle user authentication within web applications. +- Authentication Flows: Supports various authentication flows, including passwordless authentication and biometric authentication. -* Web Component Library: Offers customizable web components that can be easily integrated into web applications. -* Profile Management: Allows users to view and manage their profile information through the profile component. -* Event Handling: Provides event listeners for authentication and session-related events, enabling customization and +- Web Component Library: Offers customizable web components that can be easily integrated into web applications. +- Profile Management: Allows users to view and manage their profile information through the profile component. +- Event Handling: Provides event listeners for authentication and session-related events, enabling customization and control over the user experience. -* Localization and Internationalization: Supports multiple languages and provides translation options for a global user +- Localization and Internationalization: Supports multiple languages and provides translation options for a global user base. -* Integration Flexibility: Offers versatile choices for integration, including CDN or npm. It supports both TypeScript +- Integration Flexibility: Offers versatile choices for integration, including CDN or npm. It supports both TypeScript and non-TypeScript environments, allowing flexibility based on the project requirements. -* Customization: Enables customization of visual styles, branding, and user interface elements to align with the overall +- Customization: Enables customization of visual styles, branding, and user interface elements to align with the overall application design. -* Documentation and Support: Offers documentation, example apps, frontend framework integration guides and support via +- Documentation and Support: Offers documentation, example apps, frontend framework integration guides and support via Slack to assist with integration and troubleshooting. ## Installation @@ -95,7 +95,7 @@ If you prefer using a CDN, you can include a script tag with the import statemen ```html ``` @@ -105,33 +105,35 @@ After importing the `register()` function, call it with the URL of the Hanko API elements with the browser's `CustomElementRegistry`. ```javascript -const {hanko} = await register("https://hanko.yourdomain.com"); +const { hanko } = await register("https://hanko.yourdomain.com"); ``` You can also pass certain options: ```javascript const defaultOptions = { - shadow: true, // Set to false if you do not want the web component to be attached to the shadow DOM. - injectStyles: true, // Set to false if you do not want to inject any default styles. - enablePasskeys: true, // Set to false if you do not want to display passkey-related content. - hidePasskeyButtonOnLogin: false, // Hides the button to sign in with a passkey on the login page. - translations: null, // Additional translations can be added here. English is used when the option is not - // present or set to `null`, whereas setting an empty object `{}` prevents the elements - // from displaying any translations. - translationsLocation: "/i18n", // The URL or path where the translation files are located. - fallbackLanguage: "en", // The fallback language to be used if a translation is not available. - storageKey: "hanko" // The name of the cookie the session token is stored in and the prefix / name of local storage keys + shadow: true, // Set to false if you do not want the web component to be attached to the shadow DOM. + injectStyles: true, // Set to false if you do not want to inject any default styles. + enablePasskeys: true, // Set to false if you do not want to display passkey-related content. + hidePasskeyButtonOnLogin: false, // Hides the button to sign in with a passkey on the login page. + translations: null, // Additional translations can be added here. English is used when the option is not + // present or set to `null`, whereas setting an empty object `{}` prevents the elements + // from displaying any translations. + translationsLocation: "/i18n", // The URL or path where the translation files are located. + fallbackLanguage: "en", // The fallback language to be used if a translation is not available. + storageKey: "hanko", // The name of the cookie the session token is stored in and the prefix / name of local storage keys }; -const {hanko} = await register("https://hanko.yourdomain.com", defaultOptions); +const { hanko } = await register( + "https://hanko.yourdomain.com", + defaultOptions +); ``` Replace "https://hanko.yourdomain.com" with the actual URL of your Hanko API. ### Embedding the Web Components - If you have followed the steps mentioned above, you should now be able to place the web components anywhere in the body of your HTML. A minimal example would look like this: @@ -139,14 +141,14 @@ of your HTML. A minimal example would look like this: ``` @@ -194,8 +196,10 @@ handler via the `frontend-sdk` (see next section). ```html ``` @@ -208,7 +212,7 @@ the `register()` function, but please take a look into the Note that you can create a `hanko-frontend-sdk` instance without having to register the web components as follows: ```js -import {Hanko} from "@teamhanko/hanko-elements"; +import { Hanko } from "@teamhanko/hanko-elements"; const hanko = new Hanko("https://hanko.yourdomain.com"); ``` @@ -225,10 +229,12 @@ additional steps (e.g. passkey registration or password recovery) via the ` { - // Login, registration or recovery has been completed successfully. You can now take control and redirect the - // user to protected pages. - console.info(`User successfully completed the registration or authorization process (user-id: "${authFlowCompletedDetail.userID}")`); -}) + // Login, registration or recovery has been completed successfully. You can now take control and redirect the + // user to protected pages. + console.info( + `User successfully completed the registration or authorization process (user-id: "${authFlowCompletedDetail.userID}")` + ); +}); ``` ##### Session Created @@ -247,9 +253,11 @@ frontend. ```js hanko.onSessionCreated((sessionDetail) => { - // A new JWT has been issued. - console.info(`Session created or updated (user-id: "${sessionDetail.userID}", jwt: ${sessionDetail.jwt})`); -}) + // A new JWT has been issued. + console.info( + `Session created or updated (user-id: "${sessionDetail.userID}", jwt: ${sessionDetail.jwt})` + ); +}); ``` ##### Session Expired @@ -259,9 +267,9 @@ the user has logged out, or deleted the account. ```js hanko.onSessionExpired(() => { - // You can redirect the user to a login page or show the `` element, or to prompt the user to log in again. - console.info("Session expired"); -}) + // You can redirect the user to a login page or show the `` element, or to prompt the user to log in again. + console.info("Session expired"); +}); ``` ##### User Logged Out @@ -271,9 +279,9 @@ triggered at the same time. ```js hanko.onUserLoggedOut(() => { - // You can redirect the user to a login page or show the `` element. - console.info("User logged out"); -}) + // You can redirect the user to a login page or show the `` element. + console.info("User logged out"); +}); ``` ##### User Deleted @@ -283,9 +291,9 @@ be triggered at the same time. ```js hanko.onUserDeleted(() => { - // You can redirect the user to a login page or show the `` element. - console.info("User has been deleted"); -}) + // You can redirect the user to a login page or show the `` element. + console.info("User has been deleted"); +}); ``` To learn what else you can do, check out the @@ -305,7 +313,7 @@ Getting the session details: const session = hanko.session.get(); if (session) { - console.info(`userID: ${session.userID}, jwt: ${session.jwt}`); + console.info(`userID: ${session.userID}, jwt: ${session.jwt}`); } ``` @@ -334,64 +342,65 @@ the [frontend-sdk docs](https://docs.hanko.io/jsdoc/hanko-frontend-sdk/). ### CSS Variables -CSS variables can be used to style the `hanko-auth` and `hanko-profile` elements to your needs. A list of all CSS +CSS variables can be used to style the `hanko-auth` and `hanko-profile` elements to your needs. A list of all CSS variables including default values can be found below: ```css -hanko-auth, hanko-profile { - /* Color Scheme */ - --color: #171717; - --color-shade-1: #8f9095; - --color-shade-2: #e5e6ef; - - --brand-color: #506cf0; - --brand-color-shade-1: #6b84fb; - --brand-contrast-color: white; - - --background-color: white; - --error-color: #e82020; - --link-color: #506cf0; - - /* Font Styles */ - --font-weight: 400; - --font-size: 14px; - --font-family: sans-serif; - - /* Border Styles */ - --border-radius: 4px; - --border-style: solid; - --border-width: 1px; - - /* Item Styles */ - --item-height: 34px; - --item-margin: .5rem 0; - - /* Container Styles */ - --container-padding: 0; - --container-max-width: 600px; - - /* Headline Styles */ - --headline1-font-size: 24px; - --headline1-font-weight: 600; - --headline1-margin: 0 0 .5rem; - - --headline2-font-size: 14px; - --headline2-font-weight: 600; - --headline2-margin: 1rem 0 .25rem; - - /* Divider Styles */ - --divider-padding: 0 42px; - --divider-visibility: visible; - - /* Link Styles */ - --link-text-decoration: none; - --link-text-decoration-hover: underline; - - /* Input Styles */ - --input-min-width: 12em; - - /* Button Styles */ - --button-min-width: max-content; +hanko-auth, +hanko-profile { + /* Color Scheme */ + --color: #171717; + --color-shade-1: #8f9095; + --color-shade-2: #e5e6ef; + + --brand-color: #506cf0; + --brand-color-shade-1: #6b84fb; + --brand-contrast-color: white; + + --background-color: white; + --error-color: #e82020; + --link-color: #506cf0; + + /* Font Styles */ + --font-weight: 400; + --font-size: 14px; + --font-family: sans-serif; + + /* Border Styles */ + --border-radius: 4px; + --border-style: solid; + --border-width: 1px; + + /* Item Styles */ + --item-height: 34px; + --item-margin: 0.5rem 0; + + /* Container Styles */ + --container-padding: 0; + --container-max-width: 600px; + + /* Headline Styles */ + --headline1-font-size: 24px; + --headline1-font-weight: 600; + --headline1-margin: 0 0 0.5rem; + + --headline2-font-size: 14px; + --headline2-font-weight: 600; + --headline2-margin: 1rem 0 0.25rem; + + /* Divider Styles */ + --divider-padding: 0 42px; + --divider-visibility: visible; + + /* Link Styles */ + --link-text-decoration: none; + --link-text-decoration-hover: underline; + + /* Input Styles */ + --input-min-width: 12em; + + /* Button Styles */ + --button-min-width: max-content; } ``` @@ -403,7 +412,7 @@ Please note that shadow parts only function when the web components are attached behavior. You can enable the shadow DOM for the components using the following code snippet: ```javascript -register("https://hanko.yourdomain.com", {shadow: true}); +register("https://hanko.yourdomain.com", { shadow: true }); // equals @@ -444,10 +453,10 @@ is applied using the tag name. ```html @@ -461,11 +470,11 @@ have the `hankoComponent` class. ```html @@ -480,9 +489,9 @@ the ID selector `#hankoAuth` and applies the styles when the `:hover` pseudo-cla ```html @@ -494,7 +503,7 @@ There is also the possibility to provide your own CSS rules when the web compone DOM: ```typescript -register("https://hanko.yourdomain.com", {shadow: false}) +register("https://hanko.yourdomain.com", { shadow: false }); ``` Please take a look at the [CSS example](https://github.com/teamhanko/hanko/raw/main/frontend/elements/example.css) file @@ -504,21 +513,24 @@ example if you like to change the background color, include the following CSS ru ```css .hanko_container { - background-color: blue !important; + background-color: blue !important; } ``` Also, you can prevent injecting any styles: ```typescript -register("https://hanko.yourdomain.com", {shadow: false, injectStyles: false}) +register("https://hanko.yourdomain.com", { + shadow: false, + injectStyles: false, +}); ``` so you don't need to override properties but provide the entirety of CSS rules: ```css .hanko_container { - background-color: blue; + background-color: blue; } /* more css rules... */ @@ -569,6 +581,7 @@ You can import them individually: import { de } from "@teamhanko/hanko-elements/i18n/de"; import { en } from "@teamhanko/hanko-elements/i18n/en"; import { fr } from "@teamhanko/hanko-elements/i18n/fr"; +import { zh } from "@teamhanko/hanko-elements/i18n/zh"; ``` Or import all translations at once: @@ -580,11 +593,11 @@ import { all } from "@teamhanko/hanko-elements/i18n/all"; After importing, provide the translations through the `register()` function: ```typescript -register("https://hanko.yourdomain.com", {translations: {de, en, fr}}); +register("https://hanko.yourdomain.com", { translations: { de, en, fr, zh } }); // or -register("https://hanko.yourdomain.com", {translations: all}); +register("https://hanko.yourdomain.com", { translations: all }); ``` You can now set the `lang` attribute of the element to the desired language: @@ -602,7 +615,7 @@ import { en } from "@teamhanko/hanko-elements/i18n/en"; en.errors.somethingWentWrong = "Aww, snap!"; -register("https://hanko.yourdomain.com", {translations: {en}}); +register("https://hanko.yourdomain.com", { translations: { en } }); ``` ### Adding New Translations @@ -638,8 +651,8 @@ Script: ```typescript register("https://hanko.yourdomain.com", { - translations: {}, // An empty object, so even the default "en" translation won't be available. - translationsLocation: "/i18n" // A public folder containing language files, e.g., "en.json". + translations: {}, // An empty object, so even the default "en" translation won't be available. + translationsLocation: "/i18n", // A public folder containing language files, e.g., "en.json". }); ``` @@ -665,12 +678,12 @@ import { en } from "@teamhanko/hanko-elements/i18n/en"; import { Translation } from "@teamhanko/hanko-elements"; const symbols: Partial = { - labels: {continue: "➔"} + labels: { continue: "➔" }, }; register("https://hanko.yourdomain.com", { - fallbackLanguage: "en", - translations: {en, symbols} + fallbackLanguage: "en", + translations: { en, symbols }, }); ``` @@ -686,7 +699,7 @@ Markup: ### Conditional Mediation / Autofill assisted Requests ```html - + ``` If the browser supports autofill assisted requests, it will hide the "Sign in with passkey" button on the login page and @@ -756,4 +769,3 @@ Found a bug? Please report on our [GitHub](https://github.com/teamhanko/hanko/is ## License The `elements` project is licensed under the [MIT License](LICENSE). - diff --git a/frontend/elements/package.json b/frontend/elements/package.json index 6fab0b43b..eedd2d2e2 100644 --- a/frontend/elements/package.json +++ b/frontend/elements/package.json @@ -14,11 +14,24 @@ }, "typesVersions": { "*": { - "elements": ["dist/Elements.d.ts"], - "i18n/de": ["dist/i18n/de.d.ts"], - "i18n/en": ["dist/i18n/en.d.ts"], - "i18n/fr": ["dist/i18n/fr.d.ts"], - "i18n/all": ["dist/i18n/all.d.ts"] + "elements": [ + "dist/Elements.d.ts" + ], + "i18n/de": [ + "dist/i18n/de.d.ts" + ], + "i18n/en": [ + "dist/i18n/en.d.ts" + ], + "i18n/fr": [ + "dist/i18n/fr.d.ts" + ], + "i18n/zh": [ + "dist/i18n/zh.d.ts" + ], + "i18n/all": [ + "dist/i18n/all.d.ts" + ] } }, "exports": { @@ -42,6 +55,11 @@ "import": "./dist/i18n/fr.js", "require": "./dist/i18n/fr.js" }, + "./i18n/zh": { + "types": "./dist/i18n/zh.d.ts", + "import": "./dist/i18n/zh.js", + "require": "./dist/i18n/zh.js" + }, "./i18n/all": { "types": "./dist/i18n/all.d.ts", "import": "./dist/i18n/all.js", diff --git a/frontend/elements/src/i18n/all.ts b/frontend/elements/src/i18n/all.ts index 47ffa5927..2b137d4da 100644 --- a/frontend/elements/src/i18n/all.ts +++ b/frontend/elements/src/i18n/all.ts @@ -2,4 +2,5 @@ import { Translations } from "./translations"; import { de } from "./de"; import { en } from "./en"; import { fr } from "./fr"; -export const all: Translations = { de, en, fr }; +import { zh } from "./zh"; +export const all: Translations = { de, en, fr, zh }; diff --git a/frontend/elements/src/i18n/zh.ts b/frontend/elements/src/i18n/zh.ts new file mode 100644 index 000000000..8a73ea6ed --- /dev/null +++ b/frontend/elements/src/i18n/zh.ts @@ -0,0 +1,110 @@ +import { Translation } from "./translations"; + +export const zh: Translation = { + headlines: { + error: "发生错误", + loginEmail: "登录或注册", + loginFinished: "登录成功", + loginPasscode: "输入验证码", + loginPassword: "输入密码", + registerAuthenticator: "保存一把密钥", + registerConfirm: "创建账号?", + registerPassword: "设置新密码", + profileEmails: "电子邮件", + profilePassword: "密码", + profilePasskeys: "密钥", + isPrimaryEmail: "主要电子邮件地址", + setPrimaryEmail: "设定主要电子邮件地址", + emailVerified: "已验证", + emailUnverified: "未验证", + emailDelete: "删除", + renamePasskey: "重命名密钥", + deletePasskey: "删除密钥", + lastUsedAt: "最后使用在", + createdAt: "创建于", + connectedAccounts: "连接的账户", + deleteAccount: "删除帐户", + }, + texts: { + enterPasscode: "输入发送到“{emailAddress}”的验证码。", + setupPasskey: + "使用密钥轻松安全地登录您的账户。注意:您的生物识别数据仅存储在您的设备上,永远不会与任何人共享。", + createAccount: "没有“{emailAddress}”的账户存在。你想要创建一个新账户吗?", + passwordFormatHint: "必须长在{minLength}和{maxLength}字符之间。", + manageEmails: "您的电子邮件地址用于通信和认证。", + changePassword: "设置新密码。", + managePasskeys: "您的密钥允许您登录此账户。", + isPrimaryEmail: + "用于通讯,验证码,以及作为密钥的用户名。要更改主要电子邮件地址,请先添加另一个电子邮件地址并设定为主要。", + setPrimaryEmail: + "设定此电子邮件地址为主要,它将被用于通讯,验证码,以及作为密钥的用户名。", + emailVerified: "此电子邮件地址已经过验证。", + emailUnverified: "此电子邮件地址尚未验证。", + emailDelete: + "如果您删除此电子邮件地址,将无法再用于登录您的账户。可能已经用此电子邮件地址创建的密钥将保持完整。", + emailDeleteThirdPartyConnection: + "如果你删除这个电子邮件地址,你将不能用它登录。你也不能再用你的{provider}帐户登录或重新连接。可能已经用此电子邮件地址创建的密钥将保持完整。", + emailDeletePrimary: + "主要电子邮件地址不能被删除。请先添加另一个电子邮件地址并设定为主要电子邮件地址。", + renamePasskey: "为密钥设定名称,帮助您识别其所存储的位置。", + deletePasskey: + "从您的账户中删除此密钥。请注意,密钥将继续存在于您的设备上,也需要在那里被删除。", + deleteAccount: "您确定要删除此账号吗?所有数据将立即被删除,且无法恢复。", + }, + labels: { + or: "或", + no: "否", + yes: "是", + email: "电子邮件", + continue: "继续", + skip: "跳过", + save: "保存", + password: "密码", + signInPassword: "使用密码登录", + signInPasscode: "使用验证码登录", + forgotYourPassword: "忘记密码了吗?", + back: "返回", + signInPasskey: "使用密钥登录", + registerAuthenticator: "设置新密钥", + signIn: "登录", + signUp: "注册", + sendNewPasscode: "发送新代码", + passwordRetryAfter: "{passwordRetryAfter}后重试", + passcodeResendAfter: "{passcodeResendAfter}后请求新的代码", + unverifiedEmail: "未验证", + primaryEmail: "主要的", + setAsPrimaryEmail: "设为主要", + verify: "验证", + delete: "删除", + newEmailAddress: "新电子邮件地址", + newPassword: "新密码", + rename: "重命名", + newPasskeyName: "新密钥名称", + addEmail: "添加电子邮件", + changePassword: "更改密码", + addPasskey: "添加密钥", + webauthnUnsupported: "您的浏览器不支持密钥", + signInWith: "通过 {provider} 登录", + deleteAccount: "是的,删除此帐户。", + }, + errors: { + somethingWentWrong: "发生技术错误。请稍后再试。", + requestTimeout: "请求超时。", + invalidPassword: "邮箱或密码错误。", + invalidPasscode: "提供的验证码不正确。", + passcodeAttemptsReached: "验证码输入次数过多。请请求新的验证码。", + tooManyRequests: "请求太频繁。请稍后重试。", + unauthorized: "您的会话已过期。请再次登录。", + invalidWebauthnCredential: "此密钥已无法使用。", + passcodeExpired: "验证码已过期。请请求新的验证码。", + userVerification: + "需要用户验证。请确保你的验证设备已经用PIN或生物识别保护。", + emailAddressAlreadyExistsError: "电子邮件地址已存在。", + maxNumOfEmailAddressesReached: "不能添加更多的电子邮件地址。", + thirdPartyAccessDenied: + "访问被拒绝。该请求已被用户取消或者供应商由于其他原因拒绝了访问。", + thirdPartyMultipleAccounts: "无法确定账户。电子邮件地址被多个账户使用。", + thirdPartyUnverifiedEmail: + "需要电子邮件验证。请与您的提供商验证使用的电子邮件地址。", + }, +}; diff --git a/frontend/elements/webpack.config.cjs b/frontend/elements/webpack.config.cjs index 13d65af31..25b760eb5 100644 --- a/frontend/elements/webpack.config.cjs +++ b/frontend/elements/webpack.config.cjs @@ -6,49 +6,56 @@ module.exports = { }, entry: { hankoElements: { - filename: 'elements.js', - import: './src/index.ts', + filename: "elements.js", + import: "./src/index.ts", library: { - type: 'module' + type: "module", }, }, de: { - filename: 'i18n/de.js', - import: './src/i18n/de.ts', + filename: "i18n/de.js", + import: "./src/i18n/de.ts", library: { - type: 'module' + type: "module", }, }, en: { - filename: 'i18n/en.js', - import: './src/i18n/en.ts', + filename: "i18n/en.js", + import: "./src/i18n/en.ts", library: { - type: 'module' + type: "module", }, }, fr: { - filename: 'i18n/fr.js', - import: './src/i18n/fr.ts', + filename: "i18n/fr.js", + import: "./src/i18n/fr.ts", library: { - type: 'module' + type: "module", + }, + }, + fr: { + filename: "i18n/zh.js", + import: "./src/i18n/zh.ts", + library: { + type: "module", }, }, all: { - filename: 'i18n/all.js', - import: './src/i18n/all.ts', + filename: "i18n/all.js", + import: "./src/i18n/all.ts", library: { - type: 'module' + type: "module", }, - } + }, }, module: { rules: [ { test: /\.(tsx?)$/, - use: 'ts-loader', + use: "ts-loader", exclude: [/node_modules/, /dist/], resolve: { - fullySpecified: false + fullySpecified: false, }, }, { @@ -57,7 +64,7 @@ module.exports = { { loader: "style-loader", options: { - injectType: 'singletonStyleTag', + injectType: "singletonStyleTag", insert: (styleTag) => { // eslint-disable-next-line no-underscore-dangle window._hankoStyle = styleTag; @@ -65,36 +72,30 @@ module.exports = { }, }, { - loader: 'css-loader', + loader: "css-loader", options: { modules: { localIdentName: "hanko_[local]", localIdentContext: path.resolve(__dirname, "src"), }, importLoaders: 1, - } + }, }, { loader: "sass-loader", options: { sourceMap: true, - } - } - ] + }, + }, + ], }, - ] + ], }, resolve: { - extensions: [ - '.ts', - '.tsx', - '.js', - '.sass', - 'declarations.d.ts' - ] + extensions: [".ts", ".tsx", ".js", ".sass", "declarations.d.ts"], }, output: { clean: true, - path: path.resolve(__dirname, 'dist'), + path: path.resolve(__dirname, "dist"), }, }; From 9dd119350c6a2ba214b9166231ca551c2f6b5fba Mon Sep 17 00:00:00 2001 From: Lennart Fleischmann Date: Wed, 13 Sep 2023 14:34:09 +0200 Subject: [PATCH 2/3] feat: add missing zh translations --- frontend/elements/src/i18n/zh.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontend/elements/src/i18n/zh.ts b/frontend/elements/src/i18n/zh.ts index 8a73ea6ed..ae0e8a99e 100644 --- a/frontend/elements/src/i18n/zh.ts +++ b/frontend/elements/src/i18n/zh.ts @@ -4,6 +4,7 @@ export const zh: Translation = { headlines: { error: "发生错误", loginEmail: "登录或注册", + loginEmailNoSignup: "登录", loginFinished: "登录成功", loginPasscode: "输入验证码", loginPassword: "输入密码", @@ -24,6 +25,7 @@ export const zh: Translation = { createdAt: "创建于", connectedAccounts: "连接的账户", deleteAccount: "删除帐户", + accountNotFound: "未找到帐户", }, texts: { enterPasscode: "输入发送到“{emailAddress}”的验证码。", @@ -50,6 +52,7 @@ export const zh: Translation = { deletePasskey: "从您的账户中删除此密钥。请注意,密钥将继续存在于您的设备上,也需要在那里被删除。", deleteAccount: "您确定要删除此账号吗?所有数据将立即被删除,且无法恢复。", + noAccountExists: '没有账户"{emailAddress}"。', }, labels: { or: "或", From 4c7fd1642fffd8b11cdc50191e8896ade6eded19 Mon Sep 17 00:00:00 2001 From: Lennart Fleischmann Date: Wed, 13 Sep 2023 15:04:41 +0200 Subject: [PATCH 3/3] chore: revert formatting --- frontend/elements/README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/frontend/elements/README.md b/frontend/elements/README.md index d8ae6b7be..0424bc57a 100644 --- a/frontend/elements/README.md +++ b/frontend/elements/README.md @@ -112,16 +112,16 @@ You can also pass certain options: ```javascript const defaultOptions = { - shadow: true, // Set to false if you do not want the web component to be attached to the shadow DOM. - injectStyles: true, // Set to false if you do not want to inject any default styles. - enablePasskeys: true, // Set to false if you do not want to display passkey-related content. + shadow: true, // Set to false if you do not want the web component to be attached to the shadow DOM. + injectStyles: true, // Set to false if you do not want to inject any default styles. + enablePasskeys: true, // Set to false if you do not want to display passkey-related content. hidePasskeyButtonOnLogin: false, // Hides the button to sign in with a passkey on the login page. - translations: null, // Additional translations can be added here. English is used when the option is not - // present or set to `null`, whereas setting an empty object `{}` prevents the elements - // from displaying any translations. - translationsLocation: "/i18n", // The URL or path where the translation files are located. - fallbackLanguage: "en", // The fallback language to be used if a translation is not available. - storageKey: "hanko", // The name of the cookie the session token is stored in and the prefix / name of local storage keys + translations: null, // Additional translations can be added here. English is used when the option is not + // present or set to `null`, whereas setting an empty object `{}` prevents the elements + // from displaying any translations. + translationsLocation: "/i18n", // The URL or path where the translation files are located. + fallbackLanguage: "en", // The fallback language to be used if a translation is not available. + storageKey: "hanko", // The name of the cookie the session token is stored in and the prefix / name of local storage keys }; const { hanko } = await register(