mirror of
https://github.com/Ryujinx/Ryujinx-Website.git
synced 2024-06-02 21:28:47 +02:00
Merge 420cfae351
into 9bd5caadb7
This commit is contained in:
commit
9374611f86
|
@ -1,5 +1,12 @@
|
|||
# Release Notes
|
||||
|
||||
## v3.2.0 (15/09/2022)
|
||||
|
||||
### Features
|
||||
|
||||
- Add French language support
|
||||
- Add language selector
|
||||
|
||||
## v3.1.0 (09/09/2022)
|
||||
|
||||
### Features
|
||||
|
|
|
@ -29,13 +29,14 @@ The complete list of changes is available [here](CHANGELOG.md)
|
|||
|
||||
Currently, we need you to help us translate the website.
|
||||
Future languages to be added:
|
||||
- French
|
||||
- German
|
||||
- Dutch
|
||||
- Portuguese
|
||||
- Spanish
|
||||
- Any other language
|
||||
|
||||
Follow this link to participate in the translation (via Crowdin): https://crwd.in/ryujinx-website-ryujinxorg
|
||||
If the language you want to translate does not appear. Contact us on Discord
|
||||
|
||||
### Development
|
||||
|
||||
|
|
18
package-lock.json
generated
18
package-lock.json
generated
|
@ -8,6 +8,7 @@
|
|||
"name": "ryujinx-website",
|
||||
"version": "3.1.0",
|
||||
"dependencies": {
|
||||
"@headlessui/vue": "^1.7.0",
|
||||
"@heroicons/vue": "^1.0.6",
|
||||
"axios": "^0.27.2",
|
||||
"dayjs": "^1.11.5",
|
||||
|
@ -81,6 +82,17 @@
|
|||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@headlessui/vue": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@headlessui/vue/-/vue-1.7.0.tgz",
|
||||
"integrity": "sha512-ClrXMThmo9lrFjHdzDQXsopjCgRA28v+u5s/J+gIAgvS5l3tTAI84GaVghFwxobijL9c6BsVgDQ7SrJ2dS1nLw==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@heroicons/vue": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@heroicons/vue/-/vue-1.0.6.tgz",
|
||||
|
@ -3341,6 +3353,12 @@
|
|||
"strip-json-comments": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"@headlessui/vue": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@headlessui/vue/-/vue-1.7.0.tgz",
|
||||
"integrity": "sha512-ClrXMThmo9lrFjHdzDQXsopjCgRA28v+u5s/J+gIAgvS5l3tTAI84GaVghFwxobijL9c6BsVgDQ7SrJ2dS1nLw==",
|
||||
"requires": {}
|
||||
},
|
||||
"@heroicons/vue": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@heroicons/vue/-/vue-1.0.6.tgz",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "ryujinx-website",
|
||||
"version": "3.1.0",
|
||||
"version": "3.2.0",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc --noEmit && vite build",
|
||||
|
@ -12,7 +12,8 @@
|
|||
"vue-i18n": "^9.2.2",
|
||||
"@heroicons/vue": "^1.0.6",
|
||||
"axios": "^0.27.2",
|
||||
"dayjs": "^1.11.5"
|
||||
"dayjs": "^1.11.5",
|
||||
"@headlessui/vue": "^1.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^3.0.2",
|
||||
|
|
BIN
public/assets/images/flags/fr.png
Normal file
BIN
public/assets/images/flags/fr.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 285 B |
BIN
public/assets/images/flags/uk.png
Normal file
BIN
public/assets/images/flags/uk.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
|
@ -1,6 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import BaseNavigation from "@/common/components/navigations/BaseNavigation.vue";
|
||||
import SocialIconList from "@/modules/SocialIconList.vue";
|
||||
import LanguageSelector from "@/modules/LanguageSelector.vue";
|
||||
import { navigations } from "@/common/constants/navigation";
|
||||
</script>
|
||||
|
||||
|
@ -8,7 +9,7 @@ import { navigations } from "@/common/constants/navigation";
|
|||
<div class="bg-cover bg-bottom">
|
||||
<div class="bg-gray-800 bg-opacity-90 backdrop-filter backdrop-blur-sm">
|
||||
<!-- Header -->
|
||||
<header id="page-header" class="flex flex-none items-center py-10">
|
||||
<header id="page-header" class="flex flex-none items-center py-10 z-1">
|
||||
<div class="flex flex-col text-center md:flex-row md:items-center md:justify-between space-y-6 md:space-y-0 container xl:max-w-7xl mx-auto px-4 lg:px-10">
|
||||
<div>
|
||||
<RouterLink :to="{name: 'home'}" class="inline-flex items-center space-x-2 font-bold text-lg tracking-wide text-white hover:opacity-75">
|
||||
|
@ -22,6 +23,8 @@ import { navigations } from "@/common/constants/navigation";
|
|||
<div class="flex items-center justify-center space-x-3">
|
||||
<SocialIconList />
|
||||
</div>
|
||||
|
||||
<LanguageSelector />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
|
|
@ -3,6 +3,7 @@ import { useI18n } from "vue-i18n";
|
|||
|
||||
import BaseNavigation from "@/common/components/navigations/BaseNavigation.vue";
|
||||
import SocialIconList from "@/modules/SocialIconList.vue";
|
||||
import LanguageSelector from "@/modules/LanguageSelector.vue";
|
||||
import { navigations } from "@/common/constants/navigation";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
@ -15,7 +16,7 @@ const { t } = useI18n();
|
|||
>
|
||||
<div class="bg-gray-800 bg-opacity-90 backdrop-filter">
|
||||
<!-- Header -->
|
||||
<header id="page-header" class="flex flex-none items-center py-10">
|
||||
<header id="page-header" class="flex flex-none items-center py-10 z-1">
|
||||
<div
|
||||
class="flex flex-col text-center md:flex-row md:items-center md:justify-between space-y-6 md:space-y-0 container xl:max-w-7xl mx-auto px-4 lg:px-10"
|
||||
>
|
||||
|
@ -40,6 +41,8 @@ const { t } = useI18n();
|
|||
<div class="flex items-center justify-center space-x-3">
|
||||
<SocialIconList />
|
||||
</div>
|
||||
|
||||
<LanguageSelector />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
@ -52,14 +55,14 @@ const { t } = useI18n();
|
|||
tag="h1"
|
||||
class="text-3xl md:text-4xl font-extrabold mb-4 text-white"
|
||||
>
|
||||
<span class="text-red-500">{{ t("header.title2") }}</span>
|
||||
<span class="text-red-500">Nintendo Switch</span>
|
||||
</i18n-t>
|
||||
<i18n-t
|
||||
keypath="header.description"
|
||||
tag="h2"
|
||||
class="text-lg md:text-xl md:leading-relaxed font-medium text-gray-400 lg:w-2/3 mx-auto"
|
||||
>
|
||||
<span class="text-red-50">{{ t("header.author") }}</span>
|
||||
<span class="text-red-50">gdkchan</span>
|
||||
</i18n-t>
|
||||
<div
|
||||
class="flex flex-col sm:flex-row sm:items-center sm:justify-center space-y-2 sm:space-y-0 sm:space-x-2 pt-10 pb-16"
|
||||
|
|
16
src/common/constants/languages.ts
Normal file
16
src/common/constants/languages.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { Language } from "@/types";
|
||||
|
||||
export const availableLanguages: Language[] = [
|
||||
{
|
||||
id: 0,
|
||||
tag: "en",
|
||||
name: "English",
|
||||
image: "/assets/images/flags/uk.png",
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
tag: "fr",
|
||||
name: "Français",
|
||||
image: "/assets/images/flags/fr.png",
|
||||
},
|
||||
];
|
|
@ -1,12 +1,35 @@
|
|||
import { createI18n } from "vue-i18n";
|
||||
|
||||
import { en } from "@/i18n/locales/en";
|
||||
import { fr } from "@/i18n/locales/fr";
|
||||
import { availableLanguages } from "@/common/constants/languages";
|
||||
|
||||
let locale = "en";
|
||||
|
||||
try {
|
||||
const storeValue = localStorage.getItem("lang");
|
||||
|
||||
if (storeValue !== null) {
|
||||
const lang = JSON.parse(storeValue as string);
|
||||
locale = lang.tag;
|
||||
} else {
|
||||
if (navigator.language.startsWith("fr")) {
|
||||
locale = "fr";
|
||||
localStorage.setItem("lang", JSON.stringify(availableLanguages[1]));
|
||||
} else {
|
||||
localStorage.setItem("lang", JSON.stringify(availableLanguages[0]));
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Invalid lang:" + e);
|
||||
}
|
||||
|
||||
export const i18n = createI18n({
|
||||
legacy: false,
|
||||
locale: "en",
|
||||
locale: locale,
|
||||
fallbackLocale: "en",
|
||||
messages: {
|
||||
en,
|
||||
fr,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"title1": "A simple, experimental {0} emulator",
|
||||
"title2": "Nintendo Switch",
|
||||
"description": "Ryujinx is an open-source Nintendo Switch emulator created by {0} and written in C#. This emulator aims at providing excellent accuracy and performance, a user-friendly interface, and consistent builds.",
|
||||
"author": "gdkchan",
|
||||
"getStarted": "Get Started",
|
||||
"contribute": "Contribute"
|
||||
}
|
||||
|
|
4
src/i18n/locales/fr/footer.json
Normal file
4
src/i18n/locales/fr/footer.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"getStarted": "Démarrer",
|
||||
"contribute": "Contribuer"
|
||||
}
|
8
src/i18n/locales/fr/header.json
Normal file
8
src/i18n/locales/fr/header.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"title1": "Un émulateur simple et expérimental pour {0}",
|
||||
"title2": "Nintendo Switch",
|
||||
"description": "Ryujinx est un émulateur open source Nintendo Switch créé par {0} et écrit en C#. Il a pour but d'être précis et performant tout en ayant une interface conviviale et des versions régulières.",
|
||||
"author": "gdkchan",
|
||||
"getStarted": "Démarrer",
|
||||
"contribute": "Contribuer"
|
||||
}
|
17
src/i18n/locales/fr/index.ts
Normal file
17
src/i18n/locales/fr/index.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import navigations from "./navigations.json";
|
||||
import footer from "./footer.json";
|
||||
import header from "./header.json";
|
||||
import homepage from "./views/homepage.json";
|
||||
import download from "./views/download.json";
|
||||
import contribute from "./views/contribute.json";
|
||||
|
||||
export const fr = {
|
||||
navigations: navigations,
|
||||
header: header,
|
||||
footer: footer,
|
||||
views: {
|
||||
homepage: homepage,
|
||||
download: download,
|
||||
contribute: contribute
|
||||
},
|
||||
};
|
7
src/i18n/locales/fr/navigations.json
Normal file
7
src/i18n/locales/fr/navigations.json
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"blog": "Blog",
|
||||
"download": "Télécharger",
|
||||
"guide": "Guide",
|
||||
"faq": "FAQ",
|
||||
"compatibility": "Compatibilité"
|
||||
}
|
12
src/i18n/locales/fr/views/contribute.json
Normal file
12
src/i18n/locales/fr/views/contribute.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"title1": "Aidez-nous à créer le {0}",
|
||||
"title2": "meilleur émulateur pour switch",
|
||||
"subTitle": "Créée par une équipe passionnée, Ryujinx est en développement actif et toute aide est appréciée pour la maintenir.",
|
||||
"titleContribute": " Comment puis-je contribuer ?",
|
||||
"areaDevTitle": "Aider au Développement",
|
||||
"areaDevDescription": "Si vous avez de l'expérience avec le C#, les Homebrew Switch, le design graphique, l'assurance qualité logicielle ou le test logiciel, la gestion de serveur Discord ou n'importe quelle autre compétence que vous pensez utiles pour le projet Ryujinx, veuillez nous contacter sur notre serveur Discord.",
|
||||
"joinDiscord": "Rejoignez notre Discord",
|
||||
"becomePatron": "Devenez un Patron",
|
||||
"areaDonationTitle": "Aider grâce aux dons",
|
||||
"areaDonationDescription": "Si vous ne pouvez pas aider avec le développement, il y a d'autres moyens de nous soutenir. Bien que les dons monétaires ne soient en aucun cas nécessaire, nous les apprécions. Ces dons financeront l\"équipements nécessaire au développement de l'émulateur. En retour, il y certaines récompenses que vous recevrez en tant que supporter (comme par exemple l'accès à un canal réservé sur notre Discord)."
|
||||
}
|
22
src/i18n/locales/fr/views/download.json
Normal file
22
src/i18n/locales/fr/views/download.json
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"title1": "Dernier {0}",
|
||||
"title2": "Téléchargement",
|
||||
"subTitle": "N'oubliez pas de consulter {0} après l'installation",
|
||||
"startupGuide": "le guide de démarrage",
|
||||
"download": "Télécharger",
|
||||
"notSupported": "Actuellement non supporté",
|
||||
"supportPlanned": "Support prévu",
|
||||
"supportWindows": "Pour Windows 10 & 11",
|
||||
"supportLinux": "Pour les distributions Linux les plus courantes",
|
||||
"buildInformation": "Information sur la version",
|
||||
"buildRelease": "Cette version a été publiée le {0}",
|
||||
"assets": "ressources",
|
||||
"downloads": "téléchargements",
|
||||
"tag": "Étiquette",
|
||||
"manualDownload": "Téléchargement manuel",
|
||||
"olderBuilds": "Anciennes versions",
|
||||
"ldnBuildTitle": "Vous recherchez la {0} ?",
|
||||
"ldnBuild": "version LDN",
|
||||
"ldnBuildDescription": "Rendez-vous sur notre Patreon pour plus d'informations avec le lien de téléchargement gratuit",
|
||||
"learnMore": "En savoir plus"
|
||||
}
|
26
src/i18n/locales/fr/views/homepage.json
Normal file
26
src/i18n/locales/fr/views/homepage.json
Normal file
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"ourTeam": "Notre équipe",
|
||||
"ourTeamDescription": "Ces développeurs travaillent sans relâche pour confectionner le meilleur émulateur pour Switch.",
|
||||
"aboutProject": "À propos du projet",
|
||||
"featureDescription": " Écrit à partir de zéro, le développement a commencé en 2017 et continue toujours.",
|
||||
"openSource": "Open source",
|
||||
"openSourceDescription": "Développé par une équipe de passionnés, le code source de l'émulateur est disponible sur {0}.",
|
||||
"github": "GitHub",
|
||||
"crossPlatform": "Multiplateforme",
|
||||
"crossPlatformDescription": "Ryujinx est actuellement disponible pour les Windows 10/11 et Linux (le support macOS est prévu).",
|
||||
"compatibility": "Compatibilité",
|
||||
"compatibilityDescription": "Ryujinx a été testé sur {number_titles} jeux, et près de {number_playable} sont considérés comme jouables.",
|
||||
"support": "Soutien",
|
||||
"supportDescription": "Besoin d'aide ? Rejoignez-le {0} pour obtenir de l'aide ainsi que pour discuter avec d'autres passionnés d'émulation et l'équipe de développement.",
|
||||
"discord": "serveur Discord Ryujinx",
|
||||
"supportUs": "Nous soutenir",
|
||||
"trustedCommunities": "Reconnu par la communauté",
|
||||
"trustedCommunitiesDescription": "Si vous avez des contributions, des suggestions, besoin d'aide pour utiliser l'émulateur ou si vous souhaitez simplement entrer en contact avec l'équipe. Contactez-nous sur Twitter ou Discord ;)",
|
||||
"githubStar": "Étoiles GitHub",
|
||||
"playableGames": "Jeux jouables",
|
||||
"patreonContributors": "Contributeurs Patreon",
|
||||
"nameQuestion": "Pourquoi le {0} ?",
|
||||
"name": "nom",
|
||||
"nameDescription": "Prononcé {0}. Il est basé sur le nom \"Ryujin\", un mythique dieu/dragon de la mer. NX provient du nom de code interne de la Switch.",
|
||||
"spelled": "Ree-You-Jinx"
|
||||
}
|
|
@ -13,7 +13,7 @@ const { currentRoute } = useRouter();
|
|||
class="flex flex-col mx-auto w-full min-h-screen bg-gray-100"
|
||||
>
|
||||
<main id="page-content" class="flex flex-auto flex-col max-w-full">
|
||||
<div class="bg-gray-800 overflow-hidden">
|
||||
<div class="bg-gray-800">
|
||||
<BaseHeader />
|
||||
</div>
|
||||
|
||||
|
|
75
src/modules/LanguageSelector.vue
Normal file
75
src/modules/LanguageSelector.vue
Normal file
|
@ -0,0 +1,75 @@
|
|||
<template>
|
||||
<Menu as="div" class="relative inline-block">
|
||||
<MenuButton
|
||||
id="tk-dropdown-layouts-user"
|
||||
type="button"
|
||||
class="inline-flex justify-center items-center border font-semibold focus:outline-none px-3 py-2 leading-5 rounded border-gray-900 bg-gray-700 shadow-sm hover:bg-opacity-50 hover:shadow focus:ring focus:ring-gray-500 focus:ring-opacity-25 active:bg-opacity-100 active:shadow-none"
|
||||
>
|
||||
<img class="w-5 h-5" :src="availableLanguages[getCurrentLang()].image" :alt="availableLanguages[getCurrentLang()].name">
|
||||
</MenuButton>
|
||||
|
||||
<!-- Dropdown -->
|
||||
<transition
|
||||
enter-active-class="transition ease-out duration-150"
|
||||
enter-from-class="transform opacity-0 scale-75"
|
||||
enter-to-class="transform opacity-100 scale-100"
|
||||
leave-active-class="transition ease-in duration-100"
|
||||
leave-from-class="transform opacity-100 scale-100"
|
||||
leave-to-class="transform opacity-0 scale-75"
|
||||
>
|
||||
<MenuItems
|
||||
ref="languageDropdown"
|
||||
role="navigation"
|
||||
aria-labelledby="tk-dropdown-simple"
|
||||
class="absolute right-0 origin-top-right mt-2 w-48 shadow-xl rounded"
|
||||
>
|
||||
<div
|
||||
class="bg-white ring-1 ring-black ring-opacity-5 rounded divide-y divide-gray-100"
|
||||
>
|
||||
<MenuItem
|
||||
v-for="language in availableLanguages"
|
||||
:key="language.name"
|
||||
@click="changeLang(language)"
|
||||
>
|
||||
<div class="p-2 space-y-1">
|
||||
<a
|
||||
role="menuitem"
|
||||
href="javascript:void(0)"
|
||||
class="flex items-center space-x-2 rounded py-2 px-3 text-sm font-medium text-gray-600 hover:bg-gray-100 hover:text-gray-700 focus:outline-none focus:bg-gray-100 focus:text-gray-700"
|
||||
>
|
||||
<img class="w-5 h-5 object-center" :src="language.image" :alt="language.name">
|
||||
<span>{{ language.name }}</span>
|
||||
</a>
|
||||
</div>
|
||||
</MenuItem>
|
||||
</div>
|
||||
</MenuItems>
|
||||
</transition>
|
||||
</Menu>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Menu, MenuButton, MenuItems, MenuItem } from "@headlessui/vue";
|
||||
import { availableLanguages } from "@/common/constants/languages";
|
||||
import { Language } from "@/types";
|
||||
|
||||
const getCurrentLang = () => {
|
||||
try {
|
||||
const storeValue = localStorage.getItem("lang");
|
||||
const lang = JSON.parse(storeValue as string);
|
||||
|
||||
if (lang == undefined) {
|
||||
return 0;
|
||||
}
|
||||
return lang.id;
|
||||
} catch (e) {
|
||||
console.error("Invalid lang:" + e);
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
const changeLang = (language: Language) => {
|
||||
localStorage.setItem("lang", JSON.stringify(language));
|
||||
location.reload();
|
||||
};
|
||||
</script>
|
6
src/types/app/i18n.ts
Normal file
6
src/types/app/i18n.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
export type Language = {
|
||||
id: number;
|
||||
tag: string;
|
||||
name: string;
|
||||
image: string;
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
export * from "./app/i18n";
|
||||
export * from "./generic/navigation";
|
||||
export * from "./generic/teams";
|
||||
|
||||
export * from "./response/github";
|
||||
|
|
|
@ -125,9 +125,14 @@ const DISCORD_URL = import.meta.env.VITE_DISCORD_URL;
|
|||
<h4 class="text-lg font-bold mb-2">
|
||||
{{ t("views.homepage.compatibility") }}
|
||||
</h4>
|
||||
<p class="leading-relaxed text-gray-600">
|
||||
{{ t("views.homepage.compatibilityDescription") }}
|
||||
</p>
|
||||
<i18n-t
|
||||
keypath="views.homepage.compatibilityDescription"
|
||||
tag="p"
|
||||
class="leading-relaxed text-gray-600"
|
||||
>
|
||||
<template v-slot:number_titles>3 600</template>
|
||||
<template v-slot:number_playable>2 700</template>
|
||||
</i18n-t>
|
||||
</div>
|
||||
<div
|
||||
class="group bg-white p-5 transition ease-out duration-200 border-2 border-gray-200 rounded-2xl hover:border-sky-300"
|
||||
|
@ -188,7 +193,7 @@ const DISCORD_URL = import.meta.env.VITE_DISCORD_URL;
|
|||
tag="h3"
|
||||
class="text-lg md:text-xl md:leading-relaxed font-medium text-gray-200 lg:w-2/3 mx-auto"
|
||||
>
|
||||
<span class="italic">{{t("views.homepage.spelled")}}</span>
|
||||
<span class="italic">{{ t("views.homepage.spelled") }}</span>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue
Block a user