mirror of
https://iceshrimp.dev/Crimekillz/jointrashposs.git
synced 2024-11-21 08:23:50 +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
|
||||
locales_dist
|
||||
|
||||
# Crowdin Members Result
|
||||
assets/data/i18n-members.ts
|
||||
|
@ -20,6 +20,11 @@ export type MiHubMember = {
|
||||
type: 'website';
|
||||
href: string;
|
||||
})[];
|
||||
} | {
|
||||
id: 'crowdin';
|
||||
username: string;
|
||||
name?: string;
|
||||
avatar?: string;
|
||||
};
|
||||
|
||||
/** 現行のコアチームメンバー */
|
||||
|
@ -1,7 +1,7 @@
|
||||
<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">
|
||||
<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 class="text-lg">{{ member.name ?? '@' + member.username }}</div>
|
||||
<div v-if="member.name" class="text-sm opacity-80">{{ '@' + member.username }}</div>
|
||||
|
@ -248,6 +248,12 @@ _aboutUs:
|
||||
_orgPartner:
|
||||
title: "企業・団体パートナー"
|
||||
description: "こちらの企業・団体から、金銭的・技術的な観点でMisskeyの開発へご協力いただいております。"
|
||||
_hubTranslators:
|
||||
title: "Misskey Hub ローカライザー"
|
||||
description: "Misskey Hubの翻訳に協力いただいている皆さんです。"
|
||||
_coreTranslators:
|
||||
title: "Misskey ローカライザー"
|
||||
description: "Misskeyの翻訳に協力いただいている皆さんです。"
|
||||
|
||||
_i18n:
|
||||
_missing:
|
||||
|
@ -8,6 +8,7 @@ import { genLocalesJson } from './scripts/gen-locales';
|
||||
import { getStaticEndpoints } from './scripts/get-static-endpoints';
|
||||
import { locales } from './assets/data/locales';
|
||||
import type { NuxtConfig } from 'nuxt/schema';
|
||||
import { fetchCrowdinMembers } from './scripts/fetch-crowdin';
|
||||
|
||||
// 公開時のドメイン(末尾スラッシュなし)
|
||||
const baseUrl =
|
||||
@ -64,7 +65,8 @@ export default defineNuxtConfig({
|
||||
baseUrl,
|
||||
repositoryUrl,
|
||||
locales,
|
||||
}
|
||||
},
|
||||
CROWDIN_INTG_API: process.env.CROWDIN_INTG_API,
|
||||
},
|
||||
css: [
|
||||
"github-markdown-css/github-markdown.css",
|
||||
@ -170,9 +172,10 @@ export default defineNuxtConfig({
|
||||
],
|
||||
},
|
||||
hooks: {
|
||||
'build:before': (...args) => {
|
||||
'build:before': async (...args) => {
|
||||
genApiTranslationFiles(...args);
|
||||
genLocalesJson(...args);
|
||||
await fetchCrowdinMembers(...args);
|
||||
},
|
||||
},
|
||||
experimental: {
|
||||
|
@ -17,7 +17,25 @@
|
||||
</GHero>
|
||||
<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="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 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>
|
||||
@ -30,7 +48,7 @@
|
||||
</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 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>
|
||||
@ -43,7 +61,7 @@
|
||||
</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 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>
|
||||
@ -62,6 +80,22 @@
|
||||
</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>
|
||||
@ -69,7 +103,9 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import ExtIco from 'bi/box-arrow-up-right.svg';
|
||||
import { locales } from '@/assets/data/locales';
|
||||
import { coreTeamMember, coreTeamEmeriti } from '@/assets/data/team-members';
|
||||
import { hubI18nMembers } from '@/assets/data/i18n-members';
|
||||
import type { MiHubMember } from '@/assets/data/team-members';
|
||||
|
||||
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