mirror of
https://iceshrimp.dev/Crimekillz/jointrashposs.git
synced 2024-11-21 16:33:48 +01:00
(add) i18n members credit
This commit is contained in:
parent
783990a1df
commit
cee4e6b6e7
3
.gitignore
vendored
3
.gitignore
vendored
@ -25,3 +25,6 @@ logs
|
|||||||
|
|
||||||
# Locale build outputs
|
# Locale build outputs
|
||||||
locales_dist
|
locales_dist
|
||||||
|
|
||||||
|
# Crowdin Members Result
|
||||||
|
assets/data/i18n-members.ts
|
||||||
|
@ -20,6 +20,11 @@ export type MiHubMember = {
|
|||||||
type: 'website';
|
type: 'website';
|
||||||
href: string;
|
href: string;
|
||||||
})[];
|
})[];
|
||||||
|
} | {
|
||||||
|
id: 'crowdin';
|
||||||
|
username: string;
|
||||||
|
name?: string;
|
||||||
|
avatar?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 現行のコアチームメンバー */
|
/** 現行のコアチームメンバー */
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<GNuxtLink :to="`https://github.com/${member.username}`" target="_blank" class="block p-4 bg-slate-100 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 rounded-lg">
|
<GNuxtLink :to="member.id === 'crowdin' ? `https://crowdin.com/profile/${member.username}` : `https://github.com/${member.username}`" target="_blank" class="flex items-center p-4 bg-slate-100 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 rounded-lg">
|
||||||
<div class="flex space-x-4 items-center">
|
<div class="flex space-x-4 items-center">
|
||||||
<img :src="`https://avatars.githubusercontent.com/u/${member.id}?s=80&v=4`" class="block aspect-square flex-shrink-0 h-10 rounded-full" loading="lazy" />
|
<img :src="member.id === 'crowdin' ? member.avatar : `https://avatars.githubusercontent.com/u/${member.id}?s=80&v=4`" class="block aspect-square flex-shrink-0 h-10 rounded-full" loading="lazy" />
|
||||||
<div>
|
<div>
|
||||||
<div class="text-lg">{{ member.name ?? '@' + member.username }}</div>
|
<div class="text-lg">{{ member.name ?? '@' + member.username }}</div>
|
||||||
<div v-if="member.name" class="text-sm opacity-80">{{ '@' + member.username }}</div>
|
<div v-if="member.name" class="text-sm opacity-80">{{ '@' + member.username }}</div>
|
||||||
|
@ -248,6 +248,12 @@ _aboutUs:
|
|||||||
_orgPartner:
|
_orgPartner:
|
||||||
title: "企業・団体パートナー"
|
title: "企業・団体パートナー"
|
||||||
description: "こちらの企業・団体から、金銭的・技術的な観点でMisskeyの開発へご協力いただいております。"
|
description: "こちらの企業・団体から、金銭的・技術的な観点でMisskeyの開発へご協力いただいております。"
|
||||||
|
_hubTranslators:
|
||||||
|
title: "Misskey Hub ローカライザー"
|
||||||
|
description: "Misskey Hubの翻訳に協力いただいている皆さんです。"
|
||||||
|
_coreTranslators:
|
||||||
|
title: "Misskey ローカライザー"
|
||||||
|
description: "Misskeyの翻訳に協力いただいている皆さんです。"
|
||||||
|
|
||||||
_i18n:
|
_i18n:
|
||||||
_missing:
|
_missing:
|
||||||
|
@ -8,6 +8,7 @@ import { genLocalesJson } from './scripts/gen-locales';
|
|||||||
import { getStaticEndpoints } from './scripts/get-static-endpoints';
|
import { getStaticEndpoints } from './scripts/get-static-endpoints';
|
||||||
import { locales } from './assets/data/locales';
|
import { locales } from './assets/data/locales';
|
||||||
import type { NuxtConfig } from 'nuxt/schema';
|
import type { NuxtConfig } from 'nuxt/schema';
|
||||||
|
import { fetchCrowdinMembers } from './scripts/fetch-crowdin';
|
||||||
|
|
||||||
// 公開時のドメイン(末尾スラッシュなし)
|
// 公開時のドメイン(末尾スラッシュなし)
|
||||||
const baseUrl =
|
const baseUrl =
|
||||||
@ -64,7 +65,8 @@ export default defineNuxtConfig({
|
|||||||
baseUrl,
|
baseUrl,
|
||||||
repositoryUrl,
|
repositoryUrl,
|
||||||
locales,
|
locales,
|
||||||
}
|
},
|
||||||
|
CROWDIN_INTG_API: process.env.CROWDIN_INTG_API,
|
||||||
},
|
},
|
||||||
css: [
|
css: [
|
||||||
"github-markdown-css/github-markdown.css",
|
"github-markdown-css/github-markdown.css",
|
||||||
@ -170,9 +172,10 @@ export default defineNuxtConfig({
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
hooks: {
|
hooks: {
|
||||||
'build:before': (...args) => {
|
'build:before': async (...args) => {
|
||||||
genApiTranslationFiles(...args);
|
genApiTranslationFiles(...args);
|
||||||
genLocalesJson(...args);
|
genLocalesJson(...args);
|
||||||
|
await fetchCrowdinMembers(...args);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
experimental: {
|
experimental: {
|
||||||
|
@ -17,7 +17,25 @@
|
|||||||
</GHero>
|
</GHero>
|
||||||
<div class="pb-12 lg:mt-12 pt-6 bg-white dark:bg-slate-950">
|
<div class="pb-12 lg:mt-12 pt-6 bg-white dark:bg-slate-950">
|
||||||
<div class="container mx-auto max-w-screen-xl px-6 pt-4 space-y-8">
|
<div class="container mx-auto max-w-screen-xl px-6 pt-4 space-y-8">
|
||||||
<div class="grid gap-x-12 gap-y-4 w-full" :class="$style.teamRoot">
|
<GLocalNav :items="[
|
||||||
|
{
|
||||||
|
name: $t('_aboutUs._team._core.title'),
|
||||||
|
anchor: '#coreContributors',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: $t('_aboutUs._team._coreEmeriti.title'),
|
||||||
|
anchor: '#coreEmeriti',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: $t('_aboutUs._team._contributors.title'),
|
||||||
|
anchor: '#contributors',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: $t('_aboutUs._team._hubTranslators.title'),
|
||||||
|
anchor: '#hubTranslators',
|
||||||
|
},
|
||||||
|
]" />
|
||||||
|
<div class="grid gap-x-12 gap-y-4 w-full" :class="$style.teamRoot" id="coreContributors">
|
||||||
<div>
|
<div>
|
||||||
<div class="lg:sticky lg:top-32">
|
<div class="lg:sticky lg:top-32">
|
||||||
<h3 class="font-title font-bold text-2xl lg:text-2xl mb-2 lg:mb-4">{{ $t('_aboutUs._team._core.title') }}</h3>
|
<h3 class="font-title font-bold text-2xl lg:text-2xl mb-2 lg:mb-4">{{ $t('_aboutUs._team._core.title') }}</h3>
|
||||||
@ -30,7 +48,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid gap-x-12 gap-y-4 w-full" :class="$style.teamRoot">
|
<div class="grid gap-x-12 gap-y-4 w-full" :class="$style.teamRoot" id="coreEmeriti">
|
||||||
<div>
|
<div>
|
||||||
<div class="lg:sticky lg:top-32">
|
<div class="lg:sticky lg:top-32">
|
||||||
<h3 class="font-title font-bold text-2xl lg:text-2xl mb-2 lg:mb-4">{{ $t('_aboutUs._team._coreEmeriti.title') }}</h3>
|
<h3 class="font-title font-bold text-2xl lg:text-2xl mb-2 lg:mb-4">{{ $t('_aboutUs._team._coreEmeriti.title') }}</h3>
|
||||||
@ -43,7 +61,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid gap-x-12 gap-y-4 w-full" :class="$style.teamRoot">
|
<div class="grid gap-x-12 gap-y-4 w-full" :class="$style.teamRoot" id="contributors">
|
||||||
<div>
|
<div>
|
||||||
<div class="lg:sticky lg:top-32">
|
<div class="lg:sticky lg:top-32">
|
||||||
<h3 class="font-title font-bold text-2xl lg:text-2xl mb-2 lg:mb-4">{{ $t('_aboutUs._team._contributors.title') }}</h3>
|
<h3 class="font-title font-bold text-2xl lg:text-2xl mb-2 lg:mb-4">{{ $t('_aboutUs._team._contributors.title') }}</h3>
|
||||||
@ -62,6 +80,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="grid gap-x-12 gap-y-4 w-full" :class="$style.teamRoot" id="hubTranslators" v-if="hubI18nMembers">
|
||||||
|
<div>
|
||||||
|
<div class="lg:sticky lg:top-32">
|
||||||
|
<h3 class="font-title font-bold text-2xl lg:text-2xl mb-2 lg:mb-4">{{ $t('_aboutUs._team._hubTranslators.title') }}</h3>
|
||||||
|
<p>{{ $t('_aboutUs._team._hubTranslators.description') }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="grid md:grid-cols-2 gap-4">
|
||||||
|
<template v-for="members, lang in hubI18nMembers">
|
||||||
|
<h4 class="font-bold text-xl _i18n pt-4 first:pt-0 md:col-span-2" :lang="locales.find((v) => v.code === lang)?.iso">{{ locales.find((v) => v.code === lang)?.name ?? lang }}</h4>
|
||||||
|
<AboutUsTeamMember v-for="member in members" :member="member" />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -69,7 +103,9 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import ExtIco from 'bi/box-arrow-up-right.svg';
|
import ExtIco from 'bi/box-arrow-up-right.svg';
|
||||||
|
import { locales } from '@/assets/data/locales';
|
||||||
import { coreTeamMember, coreTeamEmeriti } from '@/assets/data/team-members';
|
import { coreTeamMember, coreTeamEmeriti } from '@/assets/data/team-members';
|
||||||
|
import { hubI18nMembers } from '@/assets/data/i18n-members';
|
||||||
import type { MiHubMember } from '@/assets/data/team-members';
|
import type { MiHubMember } from '@/assets/data/team-members';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
85
scripts/fetch-crowdin.ts
Normal file
85
scripts/fetch-crowdin.ts
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import { withQuery } from "ufo";
|
||||||
|
import { localesConst, type LocaleCodes } from "../assets/data/locales";
|
||||||
|
import type { PartialRecord } from "../types/others";
|
||||||
|
import { writeFileSync } from "fs";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
type CrowdinTargetLanguages = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
editorCode: string;
|
||||||
|
twoLettersCode: string;
|
||||||
|
threeLettersCode: string;
|
||||||
|
locale: string;
|
||||||
|
androidCode: string;
|
||||||
|
osxCode: string;
|
||||||
|
osxLocale: string;
|
||||||
|
pluralCategoryNames: string[];
|
||||||
|
pluralRules: string;
|
||||||
|
pluralExamples: string[];
|
||||||
|
textDirection: string;
|
||||||
|
dialectOf: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type CrowdinProjectMember = {
|
||||||
|
id: number;
|
||||||
|
username: string;
|
||||||
|
fullName: string;
|
||||||
|
role: string;
|
||||||
|
permissions: Record<string, string>;
|
||||||
|
roles: { name: string; permissions: Record<string, string> };
|
||||||
|
avatarUrl: string;
|
||||||
|
joinedAt: string;
|
||||||
|
timezone: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
export async function fetchCrowdinMembers() {
|
||||||
|
if (!process.env.CROWDIN_INTG_API) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await fetch('https://api.crowdin.com/api/v2/projects/628502', {
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${process.env.CROWDIN_INTG_API}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const projectRes = await res.json();
|
||||||
|
const out: PartialRecord<LocaleCodes, any[]> = {};
|
||||||
|
|
||||||
|
for (let i = 0; i < projectRes.data.targetLanguages.length; i++) {
|
||||||
|
const lang = projectRes.data.targetLanguages[i] as CrowdinTargetLanguages;
|
||||||
|
const correspondLocaleObject = localesConst.find((v) => v.iso === lang.locale);
|
||||||
|
if (correspondLocaleObject !== undefined) {
|
||||||
|
const res = await fetch(withQuery('https://api.crowdin.com/api/v2/projects/628502/members', {
|
||||||
|
role: 'translator',
|
||||||
|
languageId: lang.id,
|
||||||
|
limit: 24,
|
||||||
|
}), {
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${process.env.CROWDIN_INTG_API}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const membersRes = await res.json();
|
||||||
|
out[correspondLocaleObject.code] = (membersRes.data as { data: CrowdinProjectMember }[]).map((v) => ({
|
||||||
|
id: 'crowdin',
|
||||||
|
username: v.data.username,
|
||||||
|
name: v.data.fullName ? v.data.fullName : undefined,
|
||||||
|
avatar: v.data.avatarUrl ? v.data.avatarUrl : undefined,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const sourceFilePath = path.resolve(__dirname, '../assets/data/i18n-members.ts');
|
||||||
|
const tsOut = [
|
||||||
|
'/** This file is auto-generated */',
|
||||||
|
'import type { LocaleCodes } from \'@/assets/data/locales\';',
|
||||||
|
'import type { PartialRecord } from \'@/types/others\';',
|
||||||
|
'import type { MiHubMember } from \'./team-members\';',
|
||||||
|
];
|
||||||
|
tsOut.push(`export const hubI18nMembers: PartialRecord<LocaleCodes, MiHubMember[]> = ${JSON.stringify(out)};`);
|
||||||
|
writeFileSync(sourceFilePath, tsOut.join('\n'));
|
||||||
|
|
||||||
|
console.log('Crowdin (Misskey Hub) 貢献者の取得完了');
|
||||||
|
}
|
3
types/others.ts
Normal file
3
types/others.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export type PartialRecord<K extends keyof any, T> = {
|
||||||
|
[P in K]?: T;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user