1
0
mirror of https://github.com/SomboChea/ui synced 2026-01-12 22:25:52 +07:00

Compare commits

...

13 Commits

Author SHA1 Message Date
Juan Picado
f1dd3bb378 Merge branch 'master' into feat/custom-favicon 2020-05-02 22:45:08 +02:00
Jean-Francois Thuong
f8101ae90a fix: update zh-CN.json (#466)
Improve list of languages in Chinese (Simplified) and other misc improvements

Co-authored-by: Juan Picado <juanpicado19@gmail.com>
2020-05-02 09:35:08 +02:00
Juan Picado
462c287e2e Merge branch 'master' into feat/custom-favicon 2020-05-02 07:57:24 +02:00
Jean-Francois Thuong
bf54b4abab Update fr-FR.json (#467)
Improve list of languages in French
2020-05-01 20:14:09 +02:00
Priscila Oliveira
985cdb3df0 Merge branch 'master' into feat/custom-favicon 2020-05-01 17:23:41 +02:00
Meeeeow
9e91d64513 feat: custom favicon 2020-04-28 23:41:17 +08:00
Juan Picado @jotadeveloper
5e3c006cbd chore(release): 1.7.1 2020-04-27 21:37:54 +02:00
Priscila Oliveira
f44abd7dd0 fix(i18n): fixed current locale (#462)
* fix(i18n): fixed current locale

* Update i18n/translations/ja-JP.json

Co-Authored-By: hdmr14 <58992133+hdmr14@users.noreply.github.com>

Co-authored-by: hdmr14 <58992133+hdmr14@users.noreply.github.com>
2020-04-27 21:36:40 +02:00
Juan Picado @jotadeveloper
730c3471c2 chore(release): 1.7.0 2020-04-24 07:40:57 +02:00
hdmr14
25def6ccd5 feat: add japanese translations (#460)
* feat: add japanese translations

* fix: remove redundant words in ja-JP translation

Co-authored-by: Juan Picado <juanpicado19@gmail.com>
2020-04-24 07:39:09 +02:00
Juan Picado @jotadeveloper
ae0546c0e2 chore(release): 1.6.0 2020-04-23 08:24:14 +02:00
Priscila Oliveira
675ee980ee feat(lng): Added change language on the fly (#456)
* feat(lng): added change language on the fly

* fixed dropdown

* applied feedbacks

* added translation

* updated bundlesize

* fixed error

* updated snaps

* added french language

* added language in storage

* updated styles

* fixed tests
2020-04-23 08:20:41 +02:00
Liam JACK
b17368470d feat: Add french language + minor english language fix (#459)
* feat: Add french language + minor english language fix

* Added fr-FR to i18n config + DayJS locale loader

Co-authored-by: Liam JACK <1422590-liamjack@users.noreply.gitlab.com>
2020-04-17 08:42:38 +02:00
26 changed files with 1089 additions and 183 deletions

View File

@@ -2,6 +2,28 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [1.7.1](https://github.com/verdaccio/ui/compare/v1.7.0...v1.7.1) (2020-04-27)
### Bug Fixes
* **i18n:** fixed current locale ([#462](https://github.com/verdaccio/ui/issues/462)) ([f44abd7](https://github.com/verdaccio/ui/commit/f44abd7dd08a8d68b1bfc2bf0c053f3e80a343d0))
## [1.7.0](https://github.com/verdaccio/ui/compare/v1.6.0...v1.7.0) (2020-04-24)
### Features
* add japanese translations ([#460](https://github.com/verdaccio/ui/issues/460)) ([25def6c](https://github.com/verdaccio/ui/commit/25def6ccd5a42d43af1c33e7ace4bd7fdbec0e64))
## [1.6.0](https://github.com/verdaccio/ui/compare/v1.5.0...v1.6.0) (2020-04-23)
### Features
* **lng:** Added change language on the fly ([#456](https://github.com/verdaccio/ui/issues/456)) ([675ee98](https://github.com/verdaccio/ui/commit/675ee980ee2c4c789e52d38553f751bb219d1270))
* Add french language + minor english language fix ([#459](https://github.com/verdaccio/ui/issues/459)) ([b173684](https://github.com/verdaccio/ui/commit/b17368470d63878292aca3e6d2f9adc97748ebac))
## [1.5.0](https://github.com/verdaccio/ui/compare/v1.4.0...v1.5.0) (2020-04-08)

View File

@@ -5,7 +5,35 @@ import translationEN from './translations/en-US.json';
import translationPT from './translations/pt-BR.json';
import translationES from './translations/es-ES.json';
import translationDE from './translations/de-DE.json';
import translationFR from './translations/fr-FR.json';
import translationCN from './translations/zh-CN.json';
import translationJP from './translations/ja-JP.json';
const languages = {
'en-US': {
translation: translationEN,
},
'pt-BR': {
translation: translationPT,
},
'es-ES': {
translation: translationES,
},
'de-DE': {
translation: translationDE,
},
'fr-FR': {
translation: translationFR,
},
'zh-CN': {
translation: translationCN,
},
'ja-JP': {
translation: translationJP,
},
};
type Language = keyof typeof languages;
i18n
// pass the i18n instance to react-i18next.
@@ -16,25 +44,9 @@ i18n
// in case window.VEDACCIO_LANGUAGE is undefined,it will fall back to 'en-US'
lng: window?.__VERDACCIO_BASENAME_UI_OPTIONS?.language,
fallbackLng: 'en-US',
whitelist: ['en-US', 'pt-BR', 'es-ES', 'de-DE', 'zh-CN'],
whitelist: ['en-US', 'pt-BR', 'es-ES', 'de-DE', 'fr-FR', 'zh-CN', 'ja-JP'],
load: 'currentOnly',
resources: {
'en-US': {
translation: translationEN,
},
'pt-BR': {
translation: translationPT,
},
'es-ES': {
translation: translationES,
},
'de-DE': {
translation: translationDE,
},
'zh-CN': {
translation: translationCN,
},
},
resources: languages,
debug: false,
interpolation: {
escapeValue: false, // react already safes from xss
@@ -42,3 +54,4 @@ i18n
});
export default i18n;
export { Language };

View File

@@ -135,5 +135,16 @@
"app-context-not-correct-used": "Der App-Kontext wurde nicht korrekt verwendet",
"theme-context-not-correct-used": "Der Theme-Kontext wurde nicht korrekt verwendet",
"package-meta-is-required-at-detail-context": "packageMeta wird bei DetailContext benötigt"
}
},
"lng": {
"english": "Englisch",
"japanese": "Japanisch",
"portuguese": "Portugiesisch",
"spanish": "Spanisch",
"german": "Deutsch",
"chinese": "Chinesisch",
"french": "Französisch"
},
"help-to-translate": "Hilfe beim Übersetzen",
"change-language": "Sprache ändern"
}

View File

@@ -8,7 +8,7 @@
},
"dialog": {
"registry-info": {
"title": "Register Info"
"title": "Registry Info"
}
},
"header": {
@@ -132,8 +132,19 @@
"page-not-found": "404 - Page not found",
"sorry-we-could-not-find-it": "Sorry, we couldn't find it..."
},
"app-context-not-correct-used": "The app context was not correct used",
"theme-context-not-correct-used": "The theme context was not correct used",
"app-context-not-correct-used": "The app context was not used correctly",
"theme-context-not-correct-used": "The theme context was not used correctly",
"package-meta-is-required-at-detail-context": "packageMeta is required at DetailContext"
}
}
},
"lng": {
"english": "English",
"japanese": "Japanese",
"portuguese": "Portuguese",
"spanish": "Spanish",
"german": "German",
"chinese": "Chinese",
"french": "French"
},
"help-to-translate": "Help to translate",
"change-language": "Change language"
}

View File

@@ -135,5 +135,16 @@
"app-context-not-correct-used": "El contexto de la aplicación no fue correctamente usado",
"theme-context-not-correct-used": "El contexto del tema no fue correctamente usado",
"package-meta-is-required-at-detail-context": "packageMeta es requerido en DetailContext"
}
},
"lng": {
"english": "Inglés",
"japanese": "Japonés",
"portuguese": "Portugués",
"spanish": "Español",
"german": "Alemán",
"chinese": "Chino",
"french": "francés"
},
"help-to-translate": "Ayuda a traducir",
"change-language": "Cambiar idioma"
}

View File

@@ -0,0 +1,150 @@
{
"copy-to-clipboard": "Copier dans le presse-papier",
"author-anonymous": "Anonyme",
"action-bar-action": {
"visit-home-page": "Visiter la page d'accueil",
"open-an-issue": "Ouvrir un ticket",
"download-tarball": "Télécharger l'archive"
},
"dialog": {
"registry-info": {
"title": "Informations du Registry"
}
},
"header": {
"documentation": "Documentation",
"registry-info": "Informations du Registry",
"greetings": "Bonjour "
},
"search": {
"packages": "Rechercher des paquets"
},
"auto-complete": {
"loading": "En cours de chargement...",
"no-results-found": "Aucun resultat trouvé"
},
"tab": {
"uplinks": "Uplinks",
"versions": "Versions",
"dependencies": "Dépendances",
"readme": "Readme"
},
"uplinks": {
"title": "Uplinks",
"no-items": "{{name}} n'a pas de uplink."
},
"versions": {
"current-tags": "Tags courants",
"version-history": "Historique de version",
"not-available": "Non disponible"
},
"package": {
"published-on": "Publié le {{time}} •",
"version": "v{{version}}",
"visit-home-page": "Visiter la page d'accueil",
"homepage": "Page d'accueil",
"open-an-issue": "Ouvrir un ticket",
"bugs": "Bugs",
"download": "Télécharger {{what}}",
"the-tar-file": "le fichier tar",
"tarball": "Archive"
},
"dependencies": {
"has-no-dependencies": "{{package}} n'a aucune dépendance.",
"dependency-block": "{{package}}@{{version}}"
},
"form": {
"username": "Nom d'utilisateur",
"password": "Mot de passe"
},
"form-placeholder": {
"username": "Votre nom d'utilisateur",
"password": "Votre mot de passe"
},
"form-validation": {
"required-field": "Ce champ est obligatoire",
"required-min-length": "Ce champ doit faire au moins {{length}} caractères",
"unable-to-sign-in": "Connexion impossible",
"username-or-password-cant-be-empty": "Le nom d'utilisateur ou mot de passe ne peut pas être vide!"
},
"help": {
"title": "Aucun paquet publié pour l'instant.",
"sub-title": "Pour publier votre premier paquet:",
"first-step": "1. Se connecter",
"first-step-command-line": "npm adduser --registry {{registryUrl}}",
"second-step": "2. Publier",
"second-step-command-line": "npm publish --registry {{registryUrl}}",
"third-step": "3. Recharger cette page."
},
"sidebar": {
"detail": {
"latest-version": "Dernière v{{version}}",
"version": "v{{version}}"
},
"installation": {
"title": "Installation",
"install-using-yarn": "Installer avec yarn",
"install-using-yarn-command": "yarn add {{packageName}}",
"install-using-npm": "Installer avec npm",
"install-using-npm-command": "npm install {{packageName}}",
"install-using-pnpm": "Installer avec pnpm",
"install-using-pnpm-command": "pnpm install {{packageName}}"
},
"repository": {
"title": "Dépôt"
},
"author": {
"title": "Auteur"
},
"distribution": {
"title": "Dernière distribution",
"license": "Licence",
"size": "Taille",
"file-count": "nombre de fichiers"
},
"maintainers": {
"title": "Mainteneurs"
},
"contributors": {
"title": "Contributeurs"
},
"engines": {
"npm-version": "Version NPM",
"node-js": "NODE JS"
}
},
"footer": {
"powered-by": "Propulsé par",
"made-with-love-on": "Fait avec <0>♥</0> sur"
},
"button": {
"close": "Fermer",
"cancel": "Annuler",
"login": "Se connecter",
"logout": "Se déconnecter",
"go-to-the-home-page": "Aller à la page d'accueil",
"learn-more": "En savoir plus",
"fund-this-package": "<0>Financer</0> ce paquet"
},
"error": {
"unspecific": "Quelque chose a mal tourné.",
"404": {
"page-not-found": "404 - Page non trouvée",
"sorry-we-could-not-find-it": "Desolé, nous n'avons rien retrouvé..."
},
"app-context-not-correct-used": "Le contexte de l'application n'a pas été utilisé correctement",
"theme-context-not-correct-used": "Le contexte du thème n'a pas été utilisé correctement",
"package-meta-is-required-at-detail-context": "packageMeta est obligatoire à DetailContext"
},
"lng": {
"english": "Anglais",
"japanese": "Japonais",
"portuguese": "Portugais",
"spanish": "Espagnol",
"german": "Allemand",
"chinese": "Chinois",
"french": "Français"
},
"help-to-translate": "Aide à la traduction",
"change-language": "Changer la langue"
}

View File

@@ -0,0 +1,150 @@
{
"copy-to-clipboard": "クリップボードにコピー",
"author-anonymous": "匿名",
"action-bar-action": {
"visit-home-page": "ホームページへ移動",
"open-an-issue": "課題を開く",
"download-tarball": "tar形式でダウンロード"
},
"dialog": {
"registry-info": {
"title": "レジストリの設定方法"
}
},
"header": {
"documentation": "ドキュメント",
"registry-info": "レジストリ情報",
"greetings": "こんにちは、"
},
"search": {
"packages": "パッケージを検索"
},
"auto-complete": {
"loading": "ロード中...",
"no-results-found": "パッケージが見つかりませんでした"
},
"tab": {
"uplinks": "アップリンク",
"versions": "バージョン情報",
"dependencies": "依存パッケージ",
"readme": "Readme"
},
"uplinks": {
"title": "アップリンク",
"no-items": "{{name}}にアップリンクはありません"
},
"versions": {
"current-tags": "タグ一覧",
"version-history": "バージョン履歴",
"not-available": "利用できません"
},
"package": {
"published-on": "{{time}}に更新されました •",
"version": "v{{version}}",
"visit-home-page": "ホームページへ移動",
"homepage": "ホームページ",
"open-an-issue": "課題を開く",
"bugs": "バグ",
"download": "{{what}}ダウンロード",
"the-tar-file": "tar形式のファイル",
"tarball": "tar形式でダウンロード"
},
"dependencies": {
"has-no-dependencies": "{{package}}に依存パッケージはありません",
"dependency-block": "{{package}}@{{version}}"
},
"form": {
"username": "ユーザ名",
"password": "パスワード"
},
"form-placeholder": {
"username": "あなたのユーザ名",
"password": "あなたのパスワード"
},
"form-validation": {
"required-field": "この項目は必ず入力して下さい",
"required-min-length": "この項目は{{length}}文字以上入力して下さい",
"unable-to-sign-in": "サインインできません",
"username-or-password-cant-be-empty": "ユーザ名とパスワードは空にできません"
},
"help": {
"title": "まだパッケージが登録されていません",
"sub-title": "以下の手順で最初のパッケージを登録しましょう",
"first-step": "1. ログイン",
"first-step-command-line": "npm adduser --registry {{registryUrl}}",
"second-step": "2. 登録",
"second-step-command-line": "npm publish --registry {{registryUrl}}",
"third-step": "3. このページを再読み込みして下さい"
},
"sidebar": {
"detail": {
"latest-version": "最新バージョンは{{version}}です",
"version": "v{{version}}"
},
"installation": {
"title": "インストール方法",
"install-using-yarn": "yarnでインストール",
"install-using-yarn-command": "yarn add {{packageName}}",
"install-using-npm": "npmでインストール",
"install-using-npm-command": "npm install {{packageName}}",
"install-using-pnpm": "pnpmでインストール",
"install-using-pnpm-command": "pnpm install {{packageName}}"
},
"repository": {
"title": "リポジトリ"
},
"author": {
"title": "作者"
},
"distribution": {
"title": "最新の配信内容",
"license": "ライセンス",
"size": "サイズ",
"file-count": "ファイル数"
},
"maintainers": {
"title": "パッケージメンテナ"
},
"contributors": {
"title": "コントリビューター"
},
"engines": {
"npm-version": "NPM Version",
"node-js": "NODE JS"
}
},
"footer": {
"powered-by": "Powered by",
"made-with-love-on": "Made with <0>♥</0> on"
},
"button": {
"close": "閉じる",
"cancel": "キャンセル",
"login": "ログイン",
"logout": "ログアウト",
"go-to-the-home-page": "トップページに戻る",
"learn-more": "もっと知る",
"fund-this-package": "このパッケージに<0>投資</0>"
},
"error": {
"unspecific": "何か問題が発生したようです。",
"404": {
"page-not-found": "404 - Page not found",
"sorry-we-could-not-find-it": "残念ながら、ご指定のページはありませんでした…。"
},
"app-context-not-correct-used": "AppContextが正しく使用されませんでした",
"theme-context-not-correct-used": "ThemeContextが正しく使用されませんでした",
"package-meta-is-required-at-detail-context": "DetailContextではpackageMetaが必要です"
},
"lng": {
"english": "英語",
"japanese": "日本語",
"portuguese": "ポルトガル語",
"spanish": "スペイン語",
"german": "ドイツ語",
"chinese": "中国語",
"french": "フランス語"
},
"help-to-translate": "翻訳を助ける",
"change-language": "言語を変更"
}

View File

@@ -114,7 +114,7 @@
}
},
"footer": {
"powered-by": "Distribuído por",
"powered-by": "Feito por",
"made-with-love-on": "Feito com amor <0>♥</0> no(a)"
},
"button": {
@@ -135,5 +135,16 @@
"app-context-not-correct-used": "O contexto do aplicativo não foi usado corretamente",
"theme-context-not-correct-used": "O contexto do tema não foi usado corretamente",
"package-meta-is-required-at-detail-context": "packageMeta é requerido em DetailContext"
}
}
},
"lng": {
"english": "Inglês",
"japanese": "Japonês",
"portuguese": "Português",
"spanish": "Espanhol",
"german": "Alemão",
"chinese": "Chinês",
"french": "Francês"
},
"help-to-translate": "Ajude a traduzir",
"change-language": "Mudar idioma"
}

View File

@@ -109,7 +109,7 @@
"title": "贡献者"
},
"engines": {
"npm-version": "NPM Version",
"npm-version": "NPM版本",
"node-js": "NODE JS"
}
},
@@ -134,5 +134,16 @@
},
"app-context-not-correct-used": "The app context was not correct used",
"package-meta-is-required-at-detail-context": "packageMeta is required at DetailContext"
}
}
},
"lng": {
"english": "英语",
"japanese": "日语",
"portuguese": "葡萄牙语",
"spanish": "西班牙语",
"german": "德语",
"chinese": "中文",
"french": "法语"
},
"help-to-translate": "幫助翻译",
"change-language": "改变语言"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/ui-theme",
"version": "1.5.0",
"version": "1.7.1",
"description": "Verdaccio User Interface",
"author": {
"name": "Verdaccio Core Team",
@@ -140,7 +140,7 @@
"bundlesize": [
{
"path": "./static/vendors.*.js",
"maxSize": "200 kB"
"maxSize": "210 kB"
},
{
"path": "./static/main.*.js",

View File

@@ -1,11 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<App /> should display the Header component 1`] = `
.emotion-81 {
.emotion-85 {
background-color: #fff;
}
.emotion-24 {
.emotion-28 {
background-color: #4b5e40;
color: #fff;
min-height: 60px;
@@ -20,29 +20,29 @@ exports[`<App /> should display the Header component 1`] = `
}
@media (min-width:768px) {
.emotion-24 .emotion-13 {
.emotion-28 .emotion-13 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.emotion-24 .emotion-17 {
.emotion-28 .emotion-17 {
display: none;
}
.emotion-24 .e1jf5lit4 {
.emotion-28 .e1jf5lit4 {
display: none;
}
}
@media (min-width:1024px) {
.emotion-24 .emotion-23 {
.emotion-28 .emotion-27 {
padding: 0 20px;
}
@media (min-width:1275px) {
.emotion-24 .emotion-23 {
.emotion-28 .emotion-27 {
max-width: 1240px;
width: 100%;
margin: 0 auto;
@@ -50,7 +50,7 @@ exports[`<App /> should display the Header component 1`] = `
}
}
.emotion-22 {
.emotion-26 {
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
@@ -128,7 +128,7 @@ exports[`<App /> should display the Header component 1`] = `
overflow-y: auto;
}
.emotion-20 {
.emotion-24 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
@@ -140,12 +140,32 @@ exports[`<App /> should display the Header component 1`] = `
display: block;
}
.emotion-20 {
display: none;
}
@media screen and (min-width:768px) {
.emotion-20 {
display: inline-block;
}
}
.emotion-18 {
display: none;
}
@media screen and (min-width:768px) {
.emotion-18 {
display: inline-block;
}
}
.emotion-22 {
color: #fff;
}
@media screen and (min-width:1240px) {
.emotion-36 {
.emotion-40 {
max-width: 1240px;
width: 100%;
margin-left: auto;
@@ -153,7 +173,7 @@ exports[`<App /> should display the Header component 1`] = `
}
}
.emotion-79 {
.emotion-83 {
background: #f9f9f9;
border-top: 1px solid #e3e3e3;
color: #999999;
@@ -161,7 +181,7 @@ exports[`<App /> should display the Header component 1`] = `
padding: 20px;
}
.emotion-77 {
.emotion-81 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
@@ -178,7 +198,7 @@ exports[`<App /> should display the Header component 1`] = `
}
@media (min-width:768px) {
.emotion-77 {
.emotion-81 {
min-width: 400px;
max-width: 800px;
margin: auto;
@@ -190,12 +210,12 @@ exports[`<App /> should display the Header component 1`] = `
}
@media (min-width:1024px) {
.emotion-77 {
.emotion-81 {
max-width: 1240px;
}
}
.emotion-68 {
.emotion-72 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
@@ -204,7 +224,7 @@ exports[`<App /> should display the Header component 1`] = `
}
@media (min-width:768px) {
.emotion-68 {
.emotion-72 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
@@ -212,21 +232,21 @@ exports[`<App /> should display the Header component 1`] = `
}
}
.emotion-38 {
.emotion-42 {
color: #e25555;
padding: 0 5px;
}
.emotion-66 {
.emotion-70 {
position: relative;
height: 18px;
}
.emotion-66:hover .emotion-65 {
.emotion-70:hover .emotion-69 {
visibility: visible;
}
.emotion-41 {
.emotion-45 {
box-sizing: initial;
display: inline-block;
cursor: default;
@@ -235,7 +255,7 @@ exports[`<App /> should display the Header component 1`] = `
padding: 0 10px;
}
.emotion-64 {
.emotion-68 {
position: absolute;
background: #d3dddd;
padding: 1px 4px;
@@ -253,7 +273,7 @@ exports[`<App /> should display the Header component 1`] = `
top: -2px;
}
.emotion-64:before {
.emotion-68:before {
content: '';
position: absolute;
top: 29%;
@@ -266,7 +286,7 @@ exports[`<App /> should display the Header component 1`] = `
transform: rotate(90deg);
}
.emotion-44 {
.emotion-48 {
box-sizing: initial;
display: inline-block;
cursor: default;
@@ -275,7 +295,7 @@ exports[`<App /> should display the Header component 1`] = `
padding: 0 5px;
}
.emotion-75 {
.emotion-79 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
@@ -288,7 +308,7 @@ exports[`<App /> should display the Header component 1`] = `
}
@media (min-width:768px) {
.emotion-75 {
.emotion-79 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
@@ -296,7 +316,7 @@ exports[`<App /> should display the Header component 1`] = `
}
}
.emotion-73 {
.emotion-77 {
box-sizing: initial;
display: inline-block;
cursor: pointer;
@@ -305,12 +325,12 @@ exports[`<App /> should display the Header component 1`] = `
padding: 0 5px;
}
.emotion-70 {
.emotion-74 {
width: 100%;
height: auto;
}
.emotion-34 {
.emotion-38 {
-webkit-transform: translate(-50%,-50%);
-ms-transform: translate(-50%,-50%);
transform: translate(-50%,-50%);
@@ -319,14 +339,14 @@ exports[`<App /> should display the Header component 1`] = `
position: absolute;
}
.emotion-28 {
.emotion-32 {
margin: 0 0 30px 0;
border-radius: 25px;
box-shadow: 0 10px 20px 0 rgba(69,58,100,0.2);
background: #f7f8f6;
}
.emotion-26 {
.emotion-30 {
display: inline-block;
vertical-align: middle;
box-sizing: border-box;
@@ -338,7 +358,7 @@ exports[`<App /> should display the Header component 1`] = `
height: 90px;
}
.emotion-32 {
.emotion-36 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
@@ -353,19 +373,19 @@ exports[`<App /> should display the Header component 1`] = `
justify-content: center;
}
.emotion-30 {
.emotion-34 {
color: #4b5e40;
}
<div
class="MuiBox-root MuiBox-root-219 emotion-81 emotion-82"
class="MuiBox-root MuiBox-root-220 emotion-85 emotion-86"
>
<header
class="MuiPaper-root MuiPaper-elevation4 MuiAppBar-root MuiAppBar-positionStatic emotion-24 emotion-25 MuiAppBar-colorPrimary"
class="MuiPaper-root MuiPaper-elevation4 MuiAppBar-root MuiAppBar-positionStatic emotion-28 emotion-29 MuiAppBar-colorPrimary"
data-testid="header"
>
<div
class="MuiToolbar-root MuiToolbar-regular emotion-22 emotion-23 MuiToolbar-gutters"
class="MuiToolbar-root MuiToolbar-regular emotion-26 emotion-27 MuiToolbar-gutters"
>
<div
class="MuiToolbar-root MuiToolbar-regular emotion-14 emotion-15 MuiToolbar-gutters"
@@ -434,7 +454,7 @@ exports[`<App /> should display the Header component 1`] = `
</div>
</div>
<div
class="MuiToolbar-root MuiToolbar-regular emotion-20 emotion-21 MuiToolbar-gutters"
class="MuiToolbar-root MuiToolbar-regular emotion-24 emotion-25 MuiToolbar-gutters"
data-testid="header-right"
>
<button
@@ -461,8 +481,53 @@ exports[`<App /> should display the Header component 1`] = `
class="MuiTouchRipple-root"
/>
</button>
<div
class="emotion-20 emotion-21"
>
<button
class="MuiButtonBase-root MuiButton-root MuiButton-text MuiButton-colorInherit"
tabindex="0"
title="Change language"
type="button"
>
<span
class="MuiButton-label ForwardRef(Button)-label-339"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root"
focusable="false"
role="presentation"
viewBox="0 0 24 24"
>
<path
d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95c-.32-1.25-.78-2.45-1.38-3.56 1.84.63 3.37 1.91 4.33 3.56zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56-1.84-.63-3.37-1.9-4.33-3.56zm2.95-8H5.08c.96-1.66 2.49-2.93 4.33-3.56C8.81 5.55 8.35 6.75 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95c-.96 1.65-2.49 2.93-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z"
/>
</svg>
<span
class="emotion-18 emotion-19"
>
English
</span>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSvgIcon-fontSizeSmall"
focusable="false"
role="presentation"
viewBox="0 0 24 24"
>
<path
d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"
/>
</svg>
</span>
<span
class="MuiTouchRipple-root"
/>
</button>
</div>
<a
class="emotion-18 emotion-19"
class="emotion-22 emotion-23"
data-testid="header--tooltip-documentation"
href="https://verdaccio.org/docs/en/installation"
rel="noopener noreferrer"
@@ -566,28 +631,28 @@ exports[`<App /> should display the Header component 1`] = `
</div>
</header>
<div
class="MuiBox-root MuiBox-root-412 emotion-36 emotion-37"
class="MuiBox-root MuiBox-root-414 emotion-40 emotion-41"
>
<div
class="container content"
data-testid="home-page-container"
>
<div
class="emotion-34 emotion-35"
class="emotion-38 emotion-39"
data-testid="loading"
>
<div
class="emotion-28 emotion-29"
>
<div
class="emotion-26 emotion-1"
/>
</div>
<div
class="emotion-32 emotion-33"
>
<div
class="MuiCircularProgress-root emotion-30 emotion-31 MuiCircularProgress-colorPrimary MuiCircularProgress-indeterminate"
class="emotion-30 emotion-1"
/>
</div>
<div
class="emotion-36 emotion-37"
>
<div
class="MuiCircularProgress-root emotion-34 emotion-35 MuiCircularProgress-colorPrimary MuiCircularProgress-indeterminate"
role="progressbar"
style="width: 50px; height: 50px;"
>
@@ -610,26 +675,26 @@ exports[`<App /> should display the Header component 1`] = `
</div>
</div>
<div
class="emotion-79 emotion-80"
class="emotion-83 emotion-84"
>
<div
class="emotion-77 emotion-78"
class="emotion-81 emotion-82"
>
<div
class="emotion-68 emotion-69"
class="emotion-72 emotion-73"
>
Made with
<span
class="emotion-38 emotion-39"
class="emotion-42 emotion-43"
>
</span>
on
<span
class="emotion-66 emotion-67"
class="emotion-70 emotion-71"
>
<svg
class="emotion-40 emotion-41 emotion-42"
class="emotion-44 emotion-45 emotion-46"
>
<title>
Earth
@@ -639,10 +704,10 @@ exports[`<App /> should display the Header component 1`] = `
/>
</svg>
<span
class="emotion-64 emotion-65"
class="emotion-68 emotion-69"
>
<svg
class="emotion-43 emotion-44 emotion-42"
class="emotion-47 emotion-48 emotion-46"
>
<title>
Spain
@@ -652,7 +717,7 @@ exports[`<App /> should display the Header component 1`] = `
/>
</svg>
<svg
class="emotion-43 emotion-44 emotion-42"
class="emotion-47 emotion-48 emotion-46"
>
<title>
Nicaragua
@@ -662,7 +727,7 @@ exports[`<App /> should display the Header component 1`] = `
/>
</svg>
<svg
class="emotion-43 emotion-44 emotion-42"
class="emotion-47 emotion-48 emotion-46"
>
<title>
India
@@ -672,7 +737,7 @@ exports[`<App /> should display the Header component 1`] = `
/>
</svg>
<svg
class="emotion-43 emotion-44 emotion-42"
class="emotion-47 emotion-48 emotion-46"
>
<title>
Brazil
@@ -682,7 +747,7 @@ exports[`<App /> should display the Header component 1`] = `
/>
</svg>
<svg
class="emotion-43 emotion-44 emotion-42"
class="emotion-47 emotion-48 emotion-46"
>
<title>
China
@@ -692,7 +757,7 @@ exports[`<App /> should display the Header component 1`] = `
/>
</svg>
<svg
class="emotion-43 emotion-44 emotion-42"
class="emotion-47 emotion-48 emotion-46"
>
<title>
Austria
@@ -702,7 +767,7 @@ exports[`<App /> should display the Header component 1`] = `
/>
</svg>
<svg
class="emotion-43 emotion-44 emotion-42"
class="emotion-47 emotion-48 emotion-46"
>
<title>
Germany
@@ -715,16 +780,16 @@ exports[`<App /> should display the Header component 1`] = `
</span>
</div>
<div
class="emotion-75 emotion-76"
class="emotion-79 emotion-80"
>
Powered by
<span
class="emotion-43 emotion-73 emotion-74"
class="emotion-47 emotion-77 emotion-78"
title="Verdaccio"
>
<img
alt="Verdaccio"
class="emotion-70 emotion-71"
class="emotion-74 emotion-75"
src="[object Object]"
/>
</span>
@@ -736,11 +801,11 @@ exports[`<App /> should display the Header component 1`] = `
`;
exports[`<App /> should display the Loading component at the beginning 1`] = `
.emotion-71 {
.emotion-75 {
background-color: #fff;
}
.emotion-24 {
.emotion-28 {
background-color: #4b5e40;
color: #fff;
min-height: 60px;
@@ -755,29 +820,29 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
}
@media (min-width:768px) {
.emotion-24 .emotion-13 {
.emotion-28 .emotion-13 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.emotion-24 .emotion-17 {
.emotion-28 .emotion-17 {
display: none;
}
.emotion-24 .e1jf5lit4 {
.emotion-28 .e1jf5lit4 {
display: none;
}
}
@media (min-width:1024px) {
.emotion-24 .emotion-23 {
.emotion-28 .emotion-27 {
padding: 0 20px;
}
@media (min-width:1275px) {
.emotion-24 .emotion-23 {
.emotion-28 .emotion-27 {
max-width: 1240px;
width: 100%;
margin: 0 auto;
@@ -785,7 +850,7 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
}
}
.emotion-22 {
.emotion-26 {
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
@@ -863,7 +928,7 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
overflow-y: auto;
}
.emotion-20 {
.emotion-24 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
@@ -875,12 +940,32 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
display: block;
}
.emotion-20 {
display: none;
}
@media screen and (min-width:768px) {
.emotion-20 {
display: inline-block;
}
}
.emotion-18 {
display: none;
}
@media screen and (min-width:768px) {
.emotion-18 {
display: inline-block;
}
}
.emotion-22 {
color: #fff;
}
@media screen and (min-width:1240px) {
.emotion-26 {
.emotion-30 {
max-width: 1240px;
width: 100%;
margin-left: auto;
@@ -888,7 +973,7 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
}
}
.emotion-69 {
.emotion-73 {
background: #f9f9f9;
border-top: 1px solid #e3e3e3;
color: #999999;
@@ -896,7 +981,7 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
padding: 20px;
}
.emotion-67 {
.emotion-71 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
@@ -913,7 +998,7 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
}
@media (min-width:768px) {
.emotion-67 {
.emotion-71 {
min-width: 400px;
max-width: 800px;
margin: auto;
@@ -925,12 +1010,12 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
}
@media (min-width:1024px) {
.emotion-67 {
.emotion-71 {
max-width: 1240px;
}
}
.emotion-58 {
.emotion-62 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
@@ -939,7 +1024,7 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
}
@media (min-width:768px) {
.emotion-58 {
.emotion-62 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
@@ -947,21 +1032,21 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
}
}
.emotion-28 {
.emotion-32 {
color: #e25555;
padding: 0 5px;
}
.emotion-56 {
.emotion-60 {
position: relative;
height: 18px;
}
.emotion-56:hover .emotion-55 {
.emotion-60:hover .emotion-59 {
visibility: visible;
}
.emotion-31 {
.emotion-35 {
box-sizing: initial;
display: inline-block;
cursor: default;
@@ -970,7 +1055,7 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
padding: 0 10px;
}
.emotion-54 {
.emotion-58 {
position: absolute;
background: #d3dddd;
padding: 1px 4px;
@@ -988,7 +1073,7 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
top: -2px;
}
.emotion-54:before {
.emotion-58:before {
content: '';
position: absolute;
top: 29%;
@@ -1001,7 +1086,7 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
transform: rotate(90deg);
}
.emotion-34 {
.emotion-38 {
box-sizing: initial;
display: inline-block;
cursor: default;
@@ -1010,7 +1095,7 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
padding: 0 5px;
}
.emotion-65 {
.emotion-69 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
@@ -1023,7 +1108,7 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
}
@media (min-width:768px) {
.emotion-65 {
.emotion-69 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
@@ -1031,7 +1116,7 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
}
}
.emotion-63 {
.emotion-67 {
box-sizing: initial;
display: inline-block;
cursor: pointer;
@@ -1040,21 +1125,21 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
padding: 0 5px;
}
.emotion-60 {
.emotion-64 {
width: 100%;
height: auto;
}
<div
class="MuiBox-root MuiBox-root-2 emotion-71 emotion-72"
class="MuiBox-root MuiBox-root-2 emotion-75 emotion-76"
style="display: none;"
>
<header
class="MuiPaper-root MuiPaper-elevation4 MuiAppBar-root MuiAppBar-positionStatic emotion-24 emotion-25 MuiAppBar-colorPrimary"
class="MuiPaper-root MuiPaper-elevation4 MuiAppBar-root MuiAppBar-positionStatic emotion-28 emotion-29 MuiAppBar-colorPrimary"
data-testid="header"
>
<div
class="MuiToolbar-root MuiToolbar-regular emotion-22 emotion-23 MuiToolbar-gutters"
class="MuiToolbar-root MuiToolbar-regular emotion-26 emotion-27 MuiToolbar-gutters"
>
<div
class="MuiToolbar-root MuiToolbar-regular emotion-14 emotion-15 MuiToolbar-gutters"
@@ -1123,7 +1208,7 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
</div>
</div>
<div
class="MuiToolbar-root MuiToolbar-regular emotion-20 emotion-21 MuiToolbar-gutters"
class="MuiToolbar-root MuiToolbar-regular emotion-24 emotion-25 MuiToolbar-gutters"
data-testid="header-right"
>
<button
@@ -1150,8 +1235,53 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
class="MuiTouchRipple-root"
/>
</button>
<div
class="emotion-20 emotion-21"
>
<button
class="MuiButtonBase-root MuiButton-root MuiButton-text MuiButton-colorInherit"
tabindex="0"
title="Change language"
type="button"
>
<span
class="MuiButton-label ForwardRef(Button)-label-121"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root"
focusable="false"
role="presentation"
viewBox="0 0 24 24"
>
<path
d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95c-.32-1.25-.78-2.45-1.38-3.56 1.84.63 3.37 1.91 4.33 3.56zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56-1.84-.63-3.37-1.9-4.33-3.56zm2.95-8H5.08c.96-1.66 2.49-2.93 4.33-3.56C8.81 5.55 8.35 6.75 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95c-.96 1.65-2.49 2.93-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z"
/>
</svg>
<span
class="emotion-18 emotion-19"
>
English
</span>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSvgIcon-fontSizeSmall"
focusable="false"
role="presentation"
viewBox="0 0 24 24"
>
<path
d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"
/>
</svg>
</span>
<span
class="MuiTouchRipple-root"
/>
</button>
</div>
<a
class="emotion-18 emotion-19"
class="emotion-22 emotion-23"
data-testid="header--tooltip-documentation"
href="https://verdaccio.org/docs/en/installation"
rel="noopener noreferrer"
@@ -1255,29 +1385,29 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
</div>
</header>
<div
class="MuiBox-root MuiBox-root-195 emotion-26 emotion-27"
class="MuiBox-root MuiBox-root-196 emotion-30 emotion-31"
/>
<div
class="emotion-69 emotion-70"
class="emotion-73 emotion-74"
>
<div
class="emotion-67 emotion-68"
class="emotion-71 emotion-72"
>
<div
class="emotion-58 emotion-59"
class="emotion-62 emotion-63"
>
Made with
<span
class="emotion-28 emotion-29"
class="emotion-32 emotion-33"
>
</span>
on
<span
class="emotion-56 emotion-57"
class="emotion-60 emotion-61"
>
<svg
class="emotion-30 emotion-31 emotion-32"
class="emotion-34 emotion-35 emotion-36"
>
<title>
Earth
@@ -1287,10 +1417,10 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
/>
</svg>
<span
class="emotion-54 emotion-55"
class="emotion-58 emotion-59"
>
<svg
class="emotion-33 emotion-34 emotion-32"
class="emotion-37 emotion-38 emotion-36"
>
<title>
Spain
@@ -1300,7 +1430,7 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
/>
</svg>
<svg
class="emotion-33 emotion-34 emotion-32"
class="emotion-37 emotion-38 emotion-36"
>
<title>
Nicaragua
@@ -1310,7 +1440,7 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
/>
</svg>
<svg
class="emotion-33 emotion-34 emotion-32"
class="emotion-37 emotion-38 emotion-36"
>
<title>
India
@@ -1320,7 +1450,7 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
/>
</svg>
<svg
class="emotion-33 emotion-34 emotion-32"
class="emotion-37 emotion-38 emotion-36"
>
<title>
Brazil
@@ -1330,7 +1460,7 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
/>
</svg>
<svg
class="emotion-33 emotion-34 emotion-32"
class="emotion-37 emotion-38 emotion-36"
>
<title>
China
@@ -1340,7 +1470,7 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
/>
</svg>
<svg
class="emotion-33 emotion-34 emotion-32"
class="emotion-37 emotion-38 emotion-36"
>
<title>
Austria
@@ -1350,7 +1480,7 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
/>
</svg>
<svg
class="emotion-33 emotion-34 emotion-32"
class="emotion-37 emotion-38 emotion-36"
>
<title>
Germany
@@ -1363,16 +1493,16 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
</span>
</div>
<div
class="emotion-65 emotion-66"
class="emotion-69 emotion-70"
>
Powered by
<span
class="emotion-33 emotion-63 emotion-64"
class="emotion-37 emotion-67 emotion-68"
title="Verdaccio"
>
<img
alt="Verdaccio"
class="emotion-60 emotion-61"
class="emotion-64 emotion-65"
src="[object Object]"
/>
</span>

View File

@@ -25,14 +25,13 @@ function loadDayJSLocale() {
}
switch (locale.toLowerCase()) {
// At the moment we only support pt-BR, please see: i18n/translations/*
case 'pt-br':
{
require('dayjs/locale/pt-br');
dayjs.locale('pt-br');
}
break;
case 'de':
case 'de-de':
{
require('dayjs/locale/de');
dayjs.locale('de');
@@ -44,12 +43,24 @@ function loadDayJSLocale() {
dayjs.locale('es');
}
break;
case 'fr-fr':
{
require('dayjs/locale/fr');
dayjs.locale('fr');
}
break;
case 'zh-cn':
{
require('dayjs/locale/zh-cn');
dayjs.locale('zh-cn');
}
break;
case 'ja-jp':
{
require('dayjs/locale/ja');
dayjs.locale('ja');
}
break;
default:
break;
}

View File

@@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next';
import Button from '../../muiComponents/Button';
import ThemeContext from '../../design-tokens/ThemeContext';
import LanguageSwitch from '../LanguageSwitch';
import { RightSide } from './styles';
import HeaderToolTip from './HeaderToolTip';
@@ -72,6 +73,7 @@ const HeaderRight: React.FC<Props> = ({
{!withoutSearch && (
<HeaderToolTip onClick={onToggleMobileNav} title={t('search.packages')} tooltipIconType={'search'} />
)}
<LanguageSwitch />
<HeaderToolTip title={t('header.documentation')} tooltipIconType={'help'} />
<HeaderToolTip onClick={onOpenRegistryInfoDialog} title={t('header.registry-info')} tooltipIconType={'info'} />
<HeaderToolTip

View File

@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<Header /> component with logged in state should load the component in logged in state 1`] = `
.emotion-24 {
.emotion-28 {
background-color: #4b5e40;
color: #fff;
min-height: 60px;
@@ -16,29 +16,29 @@ exports[`<Header /> component with logged in state should load the component in
}
@media (min-width:768px) {
.emotion-24 .emotion-13 {
.emotion-28 .emotion-13 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.emotion-24 .emotion-17 {
.emotion-28 .emotion-17 {
display: none;
}
.emotion-24 .e1jf5lit4 {
.emotion-28 .e1jf5lit4 {
display: none;
}
}
@media (min-width:1024px) {
.emotion-24 .emotion-23 {
.emotion-28 .emotion-27 {
padding: 0 20px;
}
@media (min-width:1275px) {
.emotion-24 .emotion-23 {
.emotion-28 .emotion-27 {
max-width: 1240px;
width: 100%;
margin: 0 auto;
@@ -46,7 +46,7 @@ exports[`<Header /> component with logged in state should load the component in
}
}
.emotion-22 {
.emotion-26 {
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
@@ -124,7 +124,7 @@ exports[`<Header /> component with logged in state should load the component in
overflow-y: auto;
}
.emotion-20 {
.emotion-24 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
@@ -136,16 +136,36 @@ exports[`<Header /> component with logged in state should load the component in
display: block;
}
.emotion-20 {
display: none;
}
@media screen and (min-width:768px) {
.emotion-20 {
display: inline-block;
}
}
.emotion-18 {
display: none;
}
@media screen and (min-width:768px) {
.emotion-18 {
display: inline-block;
}
}
.emotion-22 {
color: #fff;
}
<header
class="MuiPaper-root MuiPaper-elevation4 MuiAppBar-root MuiAppBar-positionStatic emotion-24 emotion-25 MuiAppBar-colorPrimary"
class="MuiPaper-root MuiPaper-elevation4 MuiAppBar-root MuiAppBar-positionStatic emotion-28 emotion-29 MuiAppBar-colorPrimary"
data-testid="header"
>
<div
class="MuiToolbar-root MuiToolbar-regular emotion-22 emotion-23 MuiToolbar-gutters"
class="MuiToolbar-root MuiToolbar-regular emotion-26 emotion-27 MuiToolbar-gutters"
>
<div
class="MuiToolbar-root MuiToolbar-regular emotion-14 emotion-15 MuiToolbar-gutters"
@@ -214,7 +234,7 @@ exports[`<Header /> component with logged in state should load the component in
</div>
</div>
<div
class="MuiToolbar-root MuiToolbar-regular emotion-20 emotion-21 MuiToolbar-gutters"
class="MuiToolbar-root MuiToolbar-regular emotion-24 emotion-25 MuiToolbar-gutters"
data-testid="header-right"
>
<button
@@ -241,8 +261,53 @@ exports[`<Header /> component with logged in state should load the component in
class="MuiTouchRipple-root"
/>
</button>
<div
class="emotion-20 emotion-21"
>
<button
class="MuiButtonBase-root MuiButton-root MuiButton-text MuiButton-colorInherit"
tabindex="0"
title="Change language"
type="button"
>
<span
class="MuiButton-label ForwardRef(Button)-label-322"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root"
focusable="false"
role="presentation"
viewBox="0 0 24 24"
>
<path
d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95c-.32-1.25-.78-2.45-1.38-3.56 1.84.63 3.37 1.91 4.33 3.56zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56-1.84-.63-3.37-1.9-4.33-3.56zm2.95-8H5.08c.96-1.66 2.49-2.93 4.33-3.56C8.81 5.55 8.35 6.75 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95c-.96 1.65-2.49 2.93-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z"
/>
</svg>
<span
class="emotion-18 emotion-19"
>
English
</span>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSvgIcon-fontSizeSmall"
focusable="false"
role="presentation"
viewBox="0 0 24 24"
>
<path
d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"
/>
</svg>
</span>
<span
class="MuiTouchRipple-root"
/>
</button>
</div>
<a
class="emotion-18 emotion-19"
class="emotion-22 emotion-23"
data-testid="header--tooltip-documentation"
href="https://verdaccio.org/docs/en/installation"
rel="noopener noreferrer"
@@ -359,7 +424,7 @@ exports[`<Header /> component with logged in state should load the component in
`;
exports[`<Header /> component with logged in state should load the component in logged out state 1`] = `
.emotion-24 {
.emotion-28 {
background-color: #4b5e40;
color: #fff;
min-height: 60px;
@@ -374,29 +439,29 @@ exports[`<Header /> component with logged in state should load the component in
}
@media (min-width:768px) {
.emotion-24 .emotion-13 {
.emotion-28 .emotion-13 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.emotion-24 .emotion-17 {
.emotion-28 .emotion-17 {
display: none;
}
.emotion-24 .e1jf5lit4 {
.emotion-28 .e1jf5lit4 {
display: none;
}
}
@media (min-width:1024px) {
.emotion-24 .emotion-23 {
.emotion-28 .emotion-27 {
padding: 0 20px;
}
@media (min-width:1275px) {
.emotion-24 .emotion-23 {
.emotion-28 .emotion-27 {
max-width: 1240px;
width: 100%;
margin: 0 auto;
@@ -404,7 +469,7 @@ exports[`<Header /> component with logged in state should load the component in
}
}
.emotion-22 {
.emotion-26 {
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
@@ -482,7 +547,7 @@ exports[`<Header /> component with logged in state should load the component in
overflow-y: auto;
}
.emotion-20 {
.emotion-24 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
@@ -494,16 +559,36 @@ exports[`<Header /> component with logged in state should load the component in
display: block;
}
.emotion-20 {
display: none;
}
@media screen and (min-width:768px) {
.emotion-20 {
display: inline-block;
}
}
.emotion-18 {
display: none;
}
@media screen and (min-width:768px) {
.emotion-18 {
display: inline-block;
}
}
.emotion-22 {
color: #fff;
}
<header
class="MuiPaper-root MuiPaper-elevation4 MuiAppBar-root MuiAppBar-positionStatic emotion-24 emotion-25 MuiAppBar-colorPrimary"
class="MuiPaper-root MuiPaper-elevation4 MuiAppBar-root MuiAppBar-positionStatic emotion-28 emotion-29 MuiAppBar-colorPrimary"
data-testid="header"
>
<div
class="MuiToolbar-root MuiToolbar-regular emotion-22 emotion-23 MuiToolbar-gutters"
class="MuiToolbar-root MuiToolbar-regular emotion-26 emotion-27 MuiToolbar-gutters"
>
<div
class="MuiToolbar-root MuiToolbar-regular emotion-14 emotion-15 MuiToolbar-gutters"
@@ -572,7 +657,7 @@ exports[`<Header /> component with logged in state should load the component in
</div>
</div>
<div
class="MuiToolbar-root MuiToolbar-regular emotion-20 emotion-21 MuiToolbar-gutters"
class="MuiToolbar-root MuiToolbar-regular emotion-24 emotion-25 MuiToolbar-gutters"
data-testid="header-right"
>
<button
@@ -599,8 +684,53 @@ exports[`<Header /> component with logged in state should load the component in
class="MuiTouchRipple-root"
/>
</button>
<div
class="emotion-20 emotion-21"
>
<button
class="MuiButtonBase-root MuiButton-root MuiButton-text MuiButton-colorInherit"
tabindex="0"
title="Change language"
type="button"
>
<span
class="MuiButton-label ForwardRef(Button)-label-119"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root"
focusable="false"
role="presentation"
viewBox="0 0 24 24"
>
<path
d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95c-.32-1.25-.78-2.45-1.38-3.56 1.84.63 3.37 1.91 4.33 3.56zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56-1.84-.63-3.37-1.9-4.33-3.56zm2.95-8H5.08c.96-1.66 2.49-2.93 4.33-3.56C8.81 5.55 8.35 6.75 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95c-.96 1.65-2.49 2.93-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z"
/>
</svg>
<span
class="emotion-18 emotion-19"
>
English
</span>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSvgIcon-fontSizeSmall"
focusable="false"
role="presentation"
viewBox="0 0 24 24"
>
<path
d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"
/>
</svg>
</span>
<span
class="MuiTouchRipple-root"
/>
</button>
</div>
<a
class="emotion-18 emotion-19"
class="emotion-22 emotion-23"
data-testid="header--tooltip-documentation"
href="https://verdaccio.org/docs/en/installation"
rel="noopener noreferrer"

View File

@@ -11,6 +11,9 @@ import nicaragua from './img/nicaragua.svg';
import pakistan from './img/pakistan.svg';
import austria from './img/austria.svg';
import spain from './img/spain.svg';
import usa from './img/usa.svg';
import france from './img/france.svg';
import japan from './img/japan.svg';
import earth from './img/earth.svg';
import verdaccio from './img/verdaccio.svg';
import filebinary from './img/filebinary.svg';
@@ -23,11 +26,14 @@ export interface IconsMap {
brazil: string;
spain: string;
china: string;
usa: string;
nicaragua: string;
pakistan: string;
austria: string;
france: string;
germany: string;
india: string;
japan: string;
earth: string;
verdaccio: string;
license: string;
@@ -54,6 +60,9 @@ export const Icons: IconsMap = {
time,
version,
germany,
usa,
france,
japan,
};
export interface Props {

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" id="france"><path d="M38.345 88.273C17.167 88.273 0 105.44 0 126.618v258.759c0 21.177 17.167 38.345 38.345 38.345h132.322V88.273H38.345z" fill="#41479b"/><path fill="#f5f5f5" d="M170.67 88.277h170.67v335.45H170.67z"/><path d="M473.655 88.273H341.333v335.448h132.322c21.177 0 38.345-17.167 38.345-38.345V126.618c0-21.178-17.167-38.345-38.345-38.345z" fill="#ff4b55"/></svg>

After

Width:  |  Height:  |  Size: 434 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" id="japan"><path d="M473.655 88.275H38.345C17.167 88.275 0 105.442 0 126.62v258.76c0 21.177 17.167 38.345 38.345 38.345h435.31c21.177 0 38.345-17.167 38.345-38.345V126.62c0-21.178-17.167-38.345-38.345-38.345z" fill="#f5f5f5"/><circle cx="256" cy="255.999" r="97.1" fill="#ff4b55"/></svg>

After

Width:  |  Height:  |  Size: 350 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,217 @@
import React, { MouseEvent, useCallback, useState, useRef, useContext } from 'react';
import LanguageIcon from '@material-ui/icons/Language';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import i18next, { TFunction } from 'i18next';
import { useTranslation } from 'react-i18next';
import { withStyles } from '@material-ui/core/styles';
import ClickAwayListener from '@material-ui/core/ClickAwayListener';
import Grow from '@material-ui/core/Grow';
import Popper from '@material-ui/core/Popper';
import MenuList from '@material-ui/core/MenuList';
import styled from '@emotion/styled';
import { Language } from '../../../i18n/config';
import ThemeContext from '../../design-tokens/ThemeContext';
import Paper from '../../muiComponents/Paper';
import MenuItem from '../../muiComponents/MenuItem';
import Button from '../../muiComponents/Button';
import Tooltip from '../../muiComponents/Tooltip';
import Divider from '../../muiComponents/Divider';
import Box from '../../muiComponents/Box';
import { Theme } from '../../design-tokens/theme';
import Link from '../Link';
import Icon from '../Icon';
const VERDACCIO_UI_GITHUB_REPOSITORY = 'https://github.com/verdaccio/ui';
const getTranslatedCurrentLanguageDetails = (
t: TFunction,
currentLanguage: string
): { translation: string; icon: React.ComponentProps<typeof Icon>['name'] } => {
switch (currentLanguage) {
case 'fr-FR':
return {
translation: t('lng.french'),
icon: 'france',
};
case 'pt-BR':
return {
translation: t('lng.portuguese'),
icon: 'brazil',
};
case 'de-DE':
return {
translation: t('lng.german'),
icon: 'germany',
};
case 'es-ES':
return {
translation: t('lng.spanish'),
icon: 'spain',
};
case 'zh-CN':
return {
translation: t('lng.chinese'),
icon: 'china',
};
case 'ja-JP':
return {
translation: t('lng.japanese'),
icon: 'japan',
};
default:
return {
translation: t('lng.english'),
icon: 'usa',
};
}
};
const LanguageSwitch = () => {
const themeContext = useContext(ThemeContext);
const { t } = useTranslation();
const [open, setOpen] = useState(false);
const anchorRef = useRef<HTMLButtonElement>(null);
if (!themeContext) {
throw Error(t('theme-context-not-correct-used'));
}
const languages = (i18next.options.resources ? Object.keys(i18next.options.resources) : []) as Array<Language>;
const currentLanguage = themeContext.language;
const { translation: userLanguage } = getTranslatedCurrentLanguageDetails(t, currentLanguage);
const handleToggle = useCallback(() => {
setOpen(prevOpen => !prevOpen);
}, []);
const handleClose = useCallback(
(event: MouseEvent<HTMLLIElement | Document | HTMLAnchorElement>) => {
if (anchorRef.current) {
if (anchorRef.current.contains(event.currentTarget)) {
return;
}
}
setOpen(false);
},
[setOpen]
);
const handleSwitchLanguage = useCallback(
(language: Language) => (event: MouseEvent<HTMLLIElement>) => {
themeContext.setLanguage(language);
handleClose(event);
},
[handleClose, themeContext]
);
// return focus to the button when we transitioned from !open -> open
const prevOpen = React.useRef(open);
React.useEffect(() => {
if (prevOpen.current === true && open === false) {
if (anchorRef.current) {
anchorRef.current.focus();
}
}
prevOpen.current = open;
}, [open]);
return (
<Wrapper>
<Tooltip enterDelay={300} title={t('change-language')}>
<SwitchButton color="inherit" onClick={handleToggle} ref={anchorRef}>
<LanguageIcon />
<UserLanguage>{userLanguage}</UserLanguage>
<ExpandMoreIcon fontSize="small" />
</SwitchButton>
</Tooltip>
<Popper anchorEl={anchorRef.current} disablePortal={true} open={open} role={undefined} transition={true}>
{({ TransitionProps }) => (
<Grow {...TransitionProps}>
<StyledPaper>
<ClickAwayListener onClickAway={handleClose}>
<MenuList>
{languages
.filter(language => language !== currentLanguage)
.map(language => {
const { icon, translation } = getTranslatedCurrentLanguageDetails(t, language);
return (
<StyledMenuItem
key={language}
onClick={handleSwitchLanguage(language)}
selected={userLanguage === translation}>
<Icon name={icon} size="md" />
{translation}
</StyledMenuItem>
);
})}
<Box my={1}>
<Divider />
</Box>
<MenuItem button={true}>
<StyledLink external={true} onClick={handleClose} to={VERDACCIO_UI_GITHUB_REPOSITORY}>
{`${t('help-to-translate')}`}
</StyledLink>
</MenuItem>
</MenuList>
</ClickAwayListener>
</StyledPaper>
</Grow>
)}
</Popper>
</Wrapper>
);
};
export default LanguageSwitch;
const Wrapper = styled('div')<{ theme?: Theme }>(({ theme }) => ({
display: 'none',
[`@media screen and (min-width: ${theme && theme.breakPoints.medium}px)`]: {
display: 'inline-block',
},
}));
const UserLanguage = styled('span')<{ theme?: Theme }>(({ theme }) => ({
display: 'none',
[`@media screen and (min-width: ${theme && theme.breakPoints.medium}px)`]: {
display: 'inline-block',
},
}));
const SwitchButton = withStyles((theme: Theme) => ({
label: {
display: 'grid',
gridGap: theme?.spacing(1),
gridTemplateColumns: '24px 20px',
[`@media screen and (min-width: ${theme && theme.breakPoints.medium}px)`]: {
gridTemplateColumns: '24px 1fr 20px',
},
},
}))(Button);
const StyledMenuItem = withStyles((theme: Theme) => ({
root: {
display: 'grid',
cursor: 'pointer',
gridGap: theme?.spacing(0.5),
gridTemplateColumns: '20px 1fr',
alignItems: 'center',
'&:first-child': {
borderTopLeftRadius: 4,
borderTopRightRadius: 4,
},
},
}))(MenuItem);
const StyledLink = styled(Link)<{ theme?: Theme }>(({ theme }) => ({
color: theme?.palette.type === 'dark' ? theme?.palette.white : theme?.palette.text.primary,
textDecoration: 'none',
}));
const StyledPaper = styled(Paper)<{ theme?: Theme }>(({ theme }) => ({
backgroundColor: theme?.palette.type === 'dark' ? theme?.palette.cyanBlue : theme?.palette.white,
}));

View File

@@ -0,0 +1 @@
export { default } from './LanguageSwitch';

View File

@@ -1,8 +1,11 @@
import { createContext } from 'react';
import { Language } from '../../i18n/config';
interface Props {
isDarkMode: boolean;
setIsDarkMode: (isDarkMode: boolean) => void;
language: Language;
setLanguage: (language: Language) => void;
}
const ThemeContext = createContext<undefined | Props>(undefined);

View File

@@ -1,6 +1,7 @@
import React from 'react';
import React, { useEffect } from 'react';
import { ThemeProvider as MuiThemeProvider } from '@material-ui/core/styles';
import { ThemeProvider as EmotionThemeProvider } from 'emotion-theming';
import i18next from 'i18next';
import ThemeContext from './ThemeContext';
import { getTheme, ThemeMode } from './theme';
@@ -8,12 +9,23 @@ import useLocalStorage from './useLocalStorage';
const ThemeProvider: React.FC = ({ children }) => {
const isDarkModeDefault = window?.__VERDACCIO_BASENAME_UI_OPTIONS?.darkMode;
const currentLanguage = i18next.languages?.[0];
const [isDarkMode, setIsDarkMode] = useLocalStorage('darkMode', !!isDarkModeDefault);
const [language, setLanguage] = useLocalStorage('language', currentLanguage);
const themeMode: ThemeMode = isDarkMode ? 'dark' : 'light';
const changeLanguage = async () => {
await i18next.changeLanguage(language);
};
useEffect(() => {
changeLanguage();
}, [language, changeLanguage]);
return (
<ThemeContext.Provider value={{ isDarkMode, setIsDarkMode }}>
<ThemeContext.Provider value={{ isDarkMode, setIsDarkMode, language, setLanguage }}>
<EmotionThemeProvider theme={getTheme(themeMode)}>
<MuiThemeProvider theme={getTheme(themeMode)}>{children}</MuiThemeProvider>
</EmotionThemeProvider>

View File

@@ -9,10 +9,10 @@ interface Props extends Omit<MenuItemProps, 'component'> {
component?: HTMLElementTagName;
}
const MenuItem = forwardRef<MenuItemRef, Props>(function MenuItem({ button, ...props }, ref) {
const MenuItem = forwardRef<MenuItemRef, Props>(function MenuItem(props, ref) {
// it seems typescript has some discrimination type limitions. Please see: https://github.com/mui-org/material-ui/issues/14971
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return <StyledMaterialUIMenuItem {...props} button={button as any} innerRef={ref} />;
// @ts-ignore Type Types of property 'button' are incompatible.
return <StyledMaterialUIMenuItem {...props} ref={ref as any} />;
});
MenuItem.defaultProps = {
@@ -20,7 +20,6 @@ MenuItem.defaultProps = {
};
export default MenuItem;
const StyledMaterialUIMenuItem = styled(MaterialUIMenuItem)({
outline: 'none',
});

View File

@@ -6,7 +6,7 @@
<title>
<%= htmlWebpackPlugin.options.title %>
</title>
<link rel="icon" type="image/png" href="<%= htmlWebpackPlugin.options.verdaccioURL %>/-/static/favicon.ico" />
<link rel="icon" type="image/png" href="<%= htmlWebpackPlugin.options.verdaccioURL %>/-/mapped/favicon" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
window.__VERDACCIO_BASENAME_UI_OPTIONS = JSON.parse('<%= htmlWebpackPlugin.options.__UI_OPTIONS %>');

View File

@@ -1,6 +1,6 @@
import { isObject } from 'util';
import i18n from 'i18next';
import i18next from 'i18next';
import { UpLinks } from '@verdaccio/types';
import isString from 'lodash/isString';
import dayjs from 'dayjs';
@@ -93,5 +93,5 @@ export function getRecentReleases(time: Time = {}): Time[] {
}
export function getAuthorName(authorName: string): string {
return authorName.toLowerCase() === 'anonymous' ? i18n.t('author-anonymous') : authorName;
return authorName.toLowerCase() === 'anonymous' ? i18next.t('author-anonymous') : authorName;
}

View File

@@ -49,7 +49,6 @@ const prodConf = {
logo: 'ToReplaceByLogo',
primary_color: 'ToReplaceByPrimaryColor',
filename: 'index.html',
favicon: `${env.SRC_ROOT}/template/favicon.ico`,
verdaccioURL: 'ToReplaceByVerdaccio',
version_app: 'ToReplaceByVersion',
template: `${env.SRC_ROOT}/template/index.html`,