Merge pull request #2646 from SamantazFox/support-plurals-in-locales

Better support of plurals in locales
This commit is contained in:
Samantaz Fox 2022-01-13 12:55:55 +01:00 committed by GitHub
commit aa0724f204
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 1072 additions and 763 deletions

View file

@ -1,16 +1,14 @@
{ {
"`x` subscribers": { "generic_views_count": "{{count}} view",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` subscriber", "generic_views_count_plural": "{{count}} views",
"": "`x` subscribers" "generic_videos_count": "{{count}} video",
}, "generic_videos_count_plural": "{{count}} videos",
"`x` videos": { "generic_playlists_count": "{{count}} playlist",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` video", "generic_playlists_count_plural": "{{count}} playlists",
"": "`x` videos" "generic_subscribers_count": "{{count}} subscriber",
}, "generic_subscribers_count_plural": "{{count}} subscribers",
"`x` playlists": { "generic_subscriptions_count": "{{count}} subscription",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` playlist", "generic_subscriptions_count_plural": "{{count}} subscriptions",
"": "`x` playlists"
},
"LIVE": "LIVE", "LIVE": "LIVE",
"Shared `x` ago": "Shared `x` ago", "Shared `x` ago": "Shared `x` ago",
"Unsubscribe": "Unsubscribe", "Unsubscribe": "Unsubscribe",
@ -146,22 +144,14 @@
"Subscription manager": "Subscription manager", "Subscription manager": "Subscription manager",
"Token manager": "Token manager", "Token manager": "Token manager",
"Token": "Token", "Token": "Token",
"`x` subscriptions": { "tokens_count": "{{count}} token",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` subscription", "tokens_count_plural": "{{count}} tokens",
"": "`x` subscriptions"
},
"`x` tokens": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` token",
"": "`x` tokens"
},
"Import/export": "Import/export", "Import/export": "Import/export",
"unsubscribe": "unsubscribe", "unsubscribe": "unsubscribe",
"revoke": "revoke", "revoke": "revoke",
"Subscriptions": "Subscriptions", "Subscriptions": "Subscriptions",
"`x` unseen notifications": { "subscriptions_unseen_notifs_count": "{{count}} unseen notification",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` unseen notification", "subscriptions_unseen_notifs_count_plural": "{{count}} unseen notifications",
"": "`x` unseen notifications"
},
"search": "search", "search": "search",
"Log out": "Log out", "Log out": "Log out",
"Released under the AGPLv3 on Github.": "Released under the AGPLv3 on Github.", "Released under the AGPLv3 on Github.": "Released under the AGPLv3 on Github.",
@ -195,10 +185,6 @@
"Whitelisted regions: ": "Whitelisted regions: ", "Whitelisted regions: ": "Whitelisted regions: ",
"Blacklisted regions: ": "Blacklisted regions: ", "Blacklisted regions: ": "Blacklisted regions: ",
"Shared `x`": "Shared `x`", "Shared `x`": "Shared `x`",
"`x` views": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` view",
"": "`x` views"
},
"Premieres in `x`": "Premieres in `x`", "Premieres in `x`": "Premieres in `x`",
"Premieres `x`": "Premieres `x`", "Premieres `x`": "Premieres `x`",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.", "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.",
@ -232,16 +218,12 @@
"This channel does not exist.": "This channel does not exist.", "This channel does not exist.": "This channel does not exist.",
"Could not get channel info.": "Could not get channel info.", "Could not get channel info.": "Could not get channel info.",
"Could not fetch comments": "Could not fetch comments", "Could not fetch comments": "Could not fetch comments",
"View `x` replies": { "comments_view_x_replies": "View {{count}} reply",
"([^.,0-9]|^)1([^.,0-9]|$)": "View `x` reply", "comments_view_x_replies_plural": "View {{count}} replies",
"": "View `x` replies"
},
"`x` ago": "`x` ago", "`x` ago": "`x` ago",
"Load more": "Load more", "Load more": "Load more",
"`x` points": { "comments_points_count": "{{count}} point",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` point", "comments_points_count_plural": "{{count}} points",
"": "`x` points"
},
"Could not create mix.": "Could not create mix.", "Could not create mix.": "Could not create mix.",
"Empty playlist": "Empty playlist", "Empty playlist": "Empty playlist",
"Not a playlist.": "Not a playlist.", "Not a playlist.": "Not a playlist.",
@ -359,34 +341,20 @@
"Yiddish": "Yiddish", "Yiddish": "Yiddish",
"Yoruba": "Yoruba", "Yoruba": "Yoruba",
"Zulu": "Zulu", "Zulu": "Zulu",
"`x` years": { "generic_count_years": "{{count}} year",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` year", "generic_count_years_plural": "{{count}} years",
"": "`x` years" "generic_count_months": "{{count}} month",
}, "generic_count_months_plural": "{{count}} months",
"`x` months": { "generic_count_weeks": "{{count}} week",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` month", "generic_count_weeks_plural": "{{count}} weeks",
"": "`x` months" "generic_count_days": "{{count}} day",
}, "generic_count_days_plural": "{{count}} days",
"`x` weeks": { "generic_count_hours": "{{count}} hour",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` week", "generic_count_hours_plural": "{{count}} hours",
"": "`x` weeks" "generic_count_minutes": "{{count}} minute",
}, "generic_count_minutes_plural": "{{count}} minutes",
"`x` days": { "generic_count_seconds": "{{count}} second",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` day", "generic_count_seconds_plural": "{{count}} seconds",
"": "`x` days"
},
"`x` hours": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` hour",
"": "`x` hours"
},
"`x` minutes": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` minute",
"": "`x` minutes"
},
"`x` seconds": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` second",
"": "`x` seconds"
},
"Fallback comments: ": "Fallback comments: ", "Fallback comments: ": "Fallback comments: ",
"Popular": "Popular", "Popular": "Popular",
"Search": "Search", "Search": "Search",

View file

@ -1,16 +1,9 @@
{ {
"`x` subscribers": { "generic_views_count_0": "{{count}} بازدید",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` دنبال کننده", "generic_videos_count_0": "{{count}} ویدئو",
"": "`x` دنبال کننده" "generic_playlists_count_0": "{{count}} فهرست پخش",
}, "generic_subscribers_count_0": "{{count}} دنبال کننده",
"`x` videos": { "generic_subscriptions_count_0": "{{count}} اشتراک ها",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` ویدئو",
"": "`x` ویدئو"
},
"`x` playlists": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` فهرست پخش",
"": "`x` فهرست پخش"
},
"LIVE": "زنده", "LIVE": "زنده",
"Shared `x` ago": "`x` پیش به اشتراک گذاشته شده", "Shared `x` ago": "`x` پیش به اشتراک گذاشته شده",
"Unsubscribe": "لغو اشتراک", "Unsubscribe": "لغو اشتراک",
@ -127,22 +120,12 @@
"Subscription manager": "مدیریت اشتراک", "Subscription manager": "مدیریت اشتراک",
"Token manager": "مدیر توکن", "Token manager": "مدیر توکن",
"Token": "توکن", "Token": "توکن",
"`x` subscriptions": { "tokens_count_0": "{{count}} توکن ها",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` اشتراک ها",
"": "`x` اشتراک ها"
},
"`x` tokens": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` توکن ها",
"": "`x` توکن ها"
},
"Import/export": "وارد کردن/خارج کردن", "Import/export": "وارد کردن/خارج کردن",
"unsubscribe": "لغو اشتراک", "unsubscribe": "لغو اشتراک",
"revoke": "ابطال", "revoke": "ابطال",
"Subscriptions": "اشتراک ها", "Subscriptions": "اشتراک ها",
"`x` unseen notifications": { "subscriptions_unseen_notifs_count_0": "{{count}} اعلان نادیده",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` اعلان نادیده",
"": "`x` اعلان نادیده"
},
"search": "جستجو", "search": "جستجو",
"Log out": "خروج", "Log out": "خروج",
"Released under the AGPLv3 on Github.": "منتشر شده تحت پروانه AGPLv3 روی گیت‌هاب.", "Released under the AGPLv3 on Github.": "منتشر شده تحت پروانه AGPLv3 روی گیت‌هاب.",
@ -176,10 +159,6 @@
"Whitelisted regions: ": "مناطق لیست سفید: ", "Whitelisted regions: ": "مناطق لیست سفید: ",
"Blacklisted regions: ": "مناطق لیست سیاه: ", "Blacklisted regions: ": "مناطق لیست سیاه: ",
"Shared `x`": "به اشتراک گذاشته شده `x`", "Shared `x`": "به اشتراک گذاشته شده `x`",
"`x` views": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` بازدید",
"": "`x` بازدید"
},
"Premieres in `x`": "برای اولین بار در `x`", "Premieres in `x`": "برای اولین بار در `x`",
"Premieres `x`": "برای اولین بار `x`", "Premieres `x`": "برای اولین بار `x`",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "سلام! مثل اینکه تو جاوا اسکریپت رو خاموش کرده ای. اینجا کلیک کن تا نظرات را ببینی، این رو یادت باشه که ممکنه بارگذاری اونها کمی طول بکشه.", "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "سلام! مثل اینکه تو جاوا اسکریپت رو خاموش کرده ای. اینجا کلیک کن تا نظرات را ببینی، این رو یادت باشه که ممکنه بارگذاری اونها کمی طول بکشه.",
@ -213,16 +192,10 @@
"This channel does not exist.": "این کانال وجود ندارد.", "This channel does not exist.": "این کانال وجود ندارد.",
"Could not get channel info.": "نمیتوان اطلاعات کانال را دریافت کرد.", "Could not get channel info.": "نمیتوان اطلاعات کانال را دریافت کرد.",
"Could not fetch comments": "نمیتوان نظرات را دریافت کرد", "Could not fetch comments": "نمیتوان نظرات را دریافت کرد",
"View `x` replies": { "comments_view_x_replies_0": "نمایش {{count}} پاسخ ها",
"([^.,0-9]|^)1([^.,0-9]|$)": "نمایش `x` پاسخ ها",
"": "نمایش `x` پاسخ ها"
},
"`x` ago": "`x` پیش", "`x` ago": "`x` پیش",
"Load more": "بارگذاری بیشتر", "Load more": "بارگذاری بیشتر",
"`x` points": { "comments_points_count_0": "{{count}} نقطه ها",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` نقطه ها",
"": "`x` نقطه ها"
},
"Could not create mix.": "نمیتوان میکس ساخت.", "Could not create mix.": "نمیتوان میکس ساخت.",
"Empty playlist": "سیاههٔ پخش خالی", "Empty playlist": "سیاههٔ پخش خالی",
"Not a playlist.": "یک سیاههٔ پخش نیست.", "Not a playlist.": "یک سیاههٔ پخش نیست.",
@ -340,34 +313,13 @@
"Yiddish": "ییدیش", "Yiddish": "ییدیش",
"Yoruba": "یوروبایی", "Yoruba": "یوروبایی",
"Zulu": "زولو", "Zulu": "زولو",
"`x` years": { "generic_count_years_0": "{{count}} سال",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` سال", "generic_count_months_0": "{{count}} ماه",
"": "`x` سال" "generic_count_weeks_0": "{{count}} هفته",
}, "generic_count_days_0": "{{count}} روز",
"`x` months": { "generic_count_hours_0": "{{count}} ساعت",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` ماه", "generic_count_minutes_0": "{{count}} دقیقه",
"": "`x` ماه" "generic_count_seconds_0": "{{count}} ثانیه",
},
"`x` weeks": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` هفته",
"": "`x` هفته"
},
"`x` days": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` روز",
"": "`x` روز"
},
"`x` hours": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` ساعت",
"": "`x` ساعت"
},
"`x` minutes": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` دقیقه",
"": "`x` دقیقه"
},
"`x` seconds": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` ثانیه",
"": "`x` ثانیه"
},
"Fallback comments: ": "نظرات عقب گرد: ", "Fallback comments: ": "نظرات عقب گرد: ",
"Popular": "محبوب", "Popular": "محبوب",
"Search": "جستجو", "Search": "جستجو",

View file

@ -1,16 +1,14 @@
{ {
"`x` subscribers": { "generic_views_count": "{{count}} vue",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` abonné", "generic_views_count_plural":"{{count}} vues",
"": "`x` abonnés" "generic_videos_count": "{{count}} vidéo",
}, "generic_videos_count_plural": "{{count}} vidéos",
"`x` videos": { "generic_playlists_count": "{{count}} liste de lecture",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` vidéo", "generic_playlists_count_plural": "{{count}} listes de lecture",
"": "`x` vidéos" "generic_subscribers_count": "{{count}} abonné",
}, "generic_subscribers_count_plural": "{{count}} abonnés",
"`x` playlists": { "generic_subscriptions_count": "{{count}} abonnement",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` liste de lecture", "generic_subscriptions_count_plural": "{{count}} abonnements",
"": "`x` listes de lecture"
},
"LIVE": "EN DIRECT", "LIVE": "EN DIRECT",
"Shared `x` ago": "Ajoutée il y a `x`", "Shared `x` ago": "Ajoutée il y a `x`",
"Unsubscribe": "Se désabonner", "Unsubscribe": "Se désabonner",
@ -127,22 +125,14 @@
"Subscription manager": "Gestionnaire d'abonnement", "Subscription manager": "Gestionnaire d'abonnement",
"Token manager": "Gestionnaire de token", "Token manager": "Gestionnaire de token",
"Token": "Token", "Token": "Token",
"`x` subscriptions": { "tokens_count": "{{count}} token",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` abonnements", "tokens_count_plural": "{{count}} tokens",
"": "`x` abonnements"
},
"`x` tokens": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` token",
"": "`x` tokens"
},
"Import/export": "Importer/Exporter", "Import/export": "Importer/Exporter",
"unsubscribe": "se désabonner", "unsubscribe": "se désabonner",
"revoke": "révoquer", "revoke": "révoquer",
"Subscriptions": "Abonnements", "Subscriptions": "Abonnements",
"`x` unseen notifications": { "subscriptions_unseen_notifs_count": "{{count}} notification non vue",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` notification non vue", "subscriptions_unseen_notifs_count_plural": "{{count}} notifications non vues",
"": "`x` notifications non vues"
},
"search": "rechercher", "search": "rechercher",
"Log out": "Se déconnecter", "Log out": "Se déconnecter",
"Released under the AGPLv3 on Github.": "Publié sous licence AGPLv3 sur Github.", "Released under the AGPLv3 on Github.": "Publié sous licence AGPLv3 sur Github.",
@ -176,10 +166,6 @@
"Whitelisted regions: ": "Régions sur liste blanche : ", "Whitelisted regions: ": "Régions sur liste blanche : ",
"Blacklisted regions: ": "Régions sur liste noire : ", "Blacklisted regions: ": "Régions sur liste noire : ",
"Shared `x`": "Ajoutée le `x`", "Shared `x`": "Ajoutée le `x`",
"`x` views": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` vues",
"": "`x` vues"
},
"Premieres in `x`": "Première dans `x`", "Premieres in `x`": "Première dans `x`",
"Premieres `x`": "Première le `x`", "Premieres `x`": "Première le `x`",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Il semblerait que JavaScript soit désactivé. Cliquez ici pour voir les commentaires, mais gardez à l'esprit que le chargement peut prendre plus de temps.", "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Il semblerait que JavaScript soit désactivé. Cliquez ici pour voir les commentaires, mais gardez à l'esprit que le chargement peut prendre plus de temps.",
@ -213,16 +199,12 @@
"This channel does not exist.": "Cette chaine n'existe pas.", "This channel does not exist.": "Cette chaine n'existe pas.",
"Could not get channel info.": "Impossible de charger les informations de cette chaîne.", "Could not get channel info.": "Impossible de charger les informations de cette chaîne.",
"Could not fetch comments": "Impossible de charger les commentaires", "Could not fetch comments": "Impossible de charger les commentaires",
"View `x` replies": { "comments_view_x_replies": "Voir {{count}} réponse",
"([^.,0-9]|^)1([^.,0-9]|$)": "Voir `x` réponse", "comments_view_x_replies_plural": "Voir {{count}} réponses",
"": "Voir `x` réponses"
},
"`x` ago": "il y a `x`", "`x` ago": "il y a `x`",
"Load more": "Voir plus", "Load more": "Voir plus",
"`x` points": { "comments_points_count": "{{count}} point",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` point", "comments_points_count_plural": "{{count}} points",
"": "`x` points"
},
"Could not create mix.": "Impossible de charger cette liste de lecture.", "Could not create mix.": "Impossible de charger cette liste de lecture.",
"Empty playlist": "La liste de lecture est vide", "Empty playlist": "La liste de lecture est vide",
"Not a playlist.": "La liste de lecture est invalide.", "Not a playlist.": "La liste de lecture est invalide.",
@ -340,34 +322,20 @@
"Yiddish": "Yiddish", "Yiddish": "Yiddish",
"Yoruba": "Yoruba", "Yoruba": "Yoruba",
"Zulu": "Zoulou", "Zulu": "Zoulou",
"`x` years": { "generic_count_years": "{{count}} an",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` an", "generic_count_years_plural": "{{count}} ans",
"": "`x` ans" "generic_count_months": "{{count}} mois",
}, "generic_count_months_plural": "{{count}} mois",
"`x` months": { "generic_count_weeks": "{{count}} semaine",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` mois", "generic_count_weeks_plural": "{{count}} semaines",
"": "`x` mois" "generic_count_days": "{{count}} jour",
}, "generic_count_days_plural": "{{count}} jours",
"`x` weeks": { "generic_count_hours": "{{count}} heure",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` semaine", "generic_count_hours_plural": "{{count}} heures",
"": "`x` semaines" "generic_count_minutes": "{{count}} minute",
}, "generic_count_minutes_plural": "{{count}} minutes",
"`x` days": { "generic_count_seconds": "{{count}} seconde",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` jour", "generic_count_seconds_plural": "{{count}} secondes",
"": "`x` jours"
},
"`x` hours": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` heure",
"": "`x` heures"
},
"`x` minutes": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` minute",
"": "`x` minutes"
},
"`x` seconds": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` seconde",
"": "`x` secondes"
},
"Fallback comments: ": "Commentaires alternatifs : ", "Fallback comments: ": "Commentaires alternatifs : ",
"Popular": "Populaire", "Popular": "Populaire",
"Search": "Rechercher", "Search": "Rechercher",

View file

@ -1,16 +1,14 @@
{ {
"`x` subscribers": { "generic_views_count": "{{count}} már látta",
"": "`x` feliratkozó", "generic_views_count_plural": "{{count}} már látta",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` feliratkozó" "generic_videos_count": "{{count}} videó",
}, "generic_videos_count_plural": "{{count}} videó",
"`x` videos": { "generic_playlists_count": "{{count}} lejátszási lista",
"": "`x` videó", "generic_playlists_count_plural": "{{count}} lejátszási lista",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` videó" "generic_subscribers_count": "{{count}} feliratkozó",
}, "generic_subscribers_count_plural": "{{count}} feliratkozó",
"`x` playlists": { "generic_subscriptions_count": "{{count}} csatornára van feliratkozás",
"": "`x` lejátszási lista", "generic_subscriptions_count_plural": "{{count}} csatornára van feliratkozás",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` lejátszási lista"
},
"LIVE": "ÉLŐ", "LIVE": "ÉLŐ",
"Shared `x` ago": "`x` ezelőtt megosztva", "Shared `x` ago": "`x` ezelőtt megosztva",
"Unsubscribe": "Leiratkozás", "Unsubscribe": "Leiratkozás",
@ -124,22 +122,14 @@
"Subscription manager": "Feliratkozások kezelője", "Subscription manager": "Feliratkozások kezelője",
"Token manager": "Tokenek kezelője", "Token manager": "Tokenek kezelője",
"Token": "Token", "Token": "Token",
"`x` subscriptions": { "tokens_count": "{{count}} token",
"": "`x` csatornára van feliratkozás", "tokens_count_plural": "{{count}} token",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` csatornára van feliratkozás"
},
"`x` tokens": {
"": "`x` token",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` token"
},
"Import/export": "Importálás/exportálás", "Import/export": "Importálás/exportálás",
"unsubscribe": "leiratkozás", "unsubscribe": "leiratkozás",
"revoke": "visszavonás", "revoke": "visszavonás",
"Subscriptions": "Feliratkozások", "Subscriptions": "Feliratkozások",
"`x` unseen notifications": { "subscriptions_unseen_notifs_count": "{{count}} kimaradt értesítés",
"": "`x` kimaradt értesítés", "subscriptions_unseen_notifs_count_plural": "{{count}} kimaradt értesítés",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` kimaradt értesítés"
},
"search": "Videó keresése", "search": "Videó keresése",
"Log out": "Kijelentkezés", "Log out": "Kijelentkezés",
"Source available here.": "A forráskód itt érhető el", "Source available here.": "A forráskód itt érhető el",
@ -170,10 +160,6 @@
"Whitelisted regions: ": "Engedélyezett régiók: ", "Whitelisted regions: ": "Engedélyezett régiók: ",
"Blacklisted regions: ": "Tiltott régiók: ", "Blacklisted regions: ": "Tiltott régiók: ",
"Shared `x`": "`x` napon osztották meg", "Shared `x`": "`x` napon osztották meg",
"`x` views": {
"": "`x` már látta",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` már látta"
},
"Premieres in `x`": "`x` később lesz a premierje", "Premieres in `x`": "`x` később lesz a premierje",
"Premieres `x`": "`x` lesz a premierje", "Premieres `x`": "`x` lesz a premierje",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Helló! Úgy tűnik a JavaScript ki van kapcsolva a böngészőben. Ide kattintva lehet olvasni a hozzászólásokat, de a betöltésük így kicsit több időbe telik.", "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Helló! Úgy tűnik a JavaScript ki van kapcsolva a böngészőben. Ide kattintva lehet olvasni a hozzászólásokat, de a betöltésük így kicsit több időbe telik.",
@ -206,16 +192,12 @@
"This channel does not exist.": "Nincs ilyen csatorna.", "This channel does not exist.": "Nincs ilyen csatorna.",
"Could not get channel info.": "Nem lehetett betölteni a csatorna adatait.", "Could not get channel info.": "Nem lehetett betölteni a csatorna adatait.",
"Could not fetch comments": "Nem lehetett betölteni a hozzászólásokat.", "Could not fetch comments": "Nem lehetett betölteni a hozzászólásokat.",
"View `x` replies": { "comments_view_x_replies": "{{count}} válasz olvasása",
"": "`x` válasz olvasása", "comments_view_x_replies_plural": "{{count}} válasz olvasása",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` válasz olvasása"
},
"`x` ago": "`x` ezelőtt", "`x` ago": "`x` ezelőtt",
"Load more": "Többi hozzászólás betöltése", "Load more": "Többi hozzászólás betöltése",
"`x` points": { "comments_points_count": "{{count}} pont",
"": "`x` pont", "comments_points_count_plural": "{{count}} pont",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` pont"
},
"Could not create mix.": "A válogatást nem lehetett elkészíteni.", "Could not create mix.": "A válogatást nem lehetett elkészíteni.",
"Empty playlist": "Üres lejátszási lista", "Empty playlist": "Üres lejátszási lista",
"Not a playlist.": "Ez nem egy lejátszási lista.", "Not a playlist.": "Ez nem egy lejátszási lista.",
@ -331,34 +313,20 @@
"Yiddish": "jiddis", "Yiddish": "jiddis",
"Yoruba": "joruba", "Yoruba": "joruba",
"Zulu": "zulu", "Zulu": "zulu",
"`x` years": { "generic_count_years": "{{count}} évvel",
"": "`x` évvel", "generic_count_years_plural": "{{count}} évvel",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` évvel" "generic_count_months": "{{count}} hónappal",
}, "generic_count_months_plural": "{{count}} hónappal",
"`x` months": { "generic_count_weeks": "{{count}} héttel",
"": "`x` hónappal", "generic_count_weeks_plural": "{{count}} héttel",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` hónappal" "generic_count_days": "{{count}} nappal",
}, "generic_count_days_plural": "{{count}} nappal",
"`x` weeks": { "generic_count_hours": "{{count}} órával",
"": "`x` héttel", "generic_count_hours_plural": "{{count}} órával",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` héttel" "generic_count_minutes": "{{count}} perccel",
}, "generic_count_minutes_plural": "{{count}} perccel",
"`x` days": { "generic_count_seconds": "{{count}} másodperccel",
"": "`x` nappal", "generic_count_seconds_plural": "{{count}} másodperccel",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` nappal"
},
"`x` hours": {
"": "`x` órával",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` órával"
},
"`x` minutes": {
"": "`x` perccel",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` perccel"
},
"`x` seconds": {
"": "`x` másodperccel",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` másodperccel"
},
"Fallback comments: ": "Másodlagos kommentek: ", "Fallback comments: ": "Másodlagos kommentek: ",
"Popular": "Népszerű", "Popular": "Népszerű",
"Search": "Keresési oldal", "Search": "Keresési oldal",

View file

@ -1,16 +1,9 @@
{ {
"`x` subscribers": { "generic_views_count_0": "{{count}} tampilan",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` pelanggan", "generic_videos_count_0": "{{count}} video",
"": "`x` pelanggan" "generic_playlists_count_0": "{{count}} daftar putar",
}, "generic_subscribers_count_0": "{{count}} pelanggan",
"`x` videos": { "generic_subscriptions_count_0": "{{count}} langganan",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` video",
"": "`x` video"
},
"`x` playlists": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` daftar putar",
"": "`x` daftar putar"
},
"LIVE": "SIARAN LANGSUNG", "LIVE": "SIARAN LANGSUNG",
"Shared `x` ago": "Dibagikan `x` yang lalu", "Shared `x` ago": "Dibagikan `x` yang lalu",
"Unsubscribe": "Batal Langganan", "Unsubscribe": "Batal Langganan",
@ -127,22 +120,12 @@
"Subscription manager": "Pengatur langganan", "Subscription manager": "Pengatur langganan",
"Token manager": "Pengatur token", "Token manager": "Pengatur token",
"Token": "Token", "Token": "Token",
"`x` subscriptions": { "tokens_count_0": "{{count}} token",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` langganan",
"": "`x` langganan"
},
"`x` tokens": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` token",
"": "`x` token"
},
"Import/export": "Impor/ekspor", "Import/export": "Impor/ekspor",
"unsubscribe": "batal langganan", "unsubscribe": "batal langganan",
"revoke": "cabut", "revoke": "cabut",
"Subscriptions": "Langganan", "Subscriptions": "Langganan",
"`x` unseen notifications": { "subscriptions_unseen_notifs_count_0": "{{count}} pemberitahuan belum dilihat",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` pemberitahuan belum dilihat",
"": "`x` pemberitahuan belum dilihat"
},
"search": "cari", "search": "cari",
"Log out": "Keluar", "Log out": "Keluar",
"Released under the AGPLv3 on Github.": "Dirilis di bawah AGPLv3 di Github.", "Released under the AGPLv3 on Github.": "Dirilis di bawah AGPLv3 di Github.",
@ -176,10 +159,6 @@
"Whitelisted regions: ": "Wilayah daftar-putih: ", "Whitelisted regions: ": "Wilayah daftar-putih: ",
"Blacklisted regions: ": "Wilayah daftar-hitam: ", "Blacklisted regions: ": "Wilayah daftar-hitam: ",
"Shared `x`": "Berbagi `x`", "Shared `x`": "Berbagi `x`",
"`x` views": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` tampilan",
"": "`x` tampilan"
},
"Premieres in `x`": "Tayang dalam `x`", "Premieres in `x`": "Tayang dalam `x`",
"Premieres `x`": "Tayang `x`", "Premieres `x`": "Tayang `x`",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Hai! Kelihatannya JavaScript kamu dimatikan. Klik di sini untuk melihat komentar, perlu diingat hal ini mungkin membutuhkan waktu sedikit lebih lama untuk dimuat.", "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Hai! Kelihatannya JavaScript kamu dimatikan. Klik di sini untuk melihat komentar, perlu diingat hal ini mungkin membutuhkan waktu sedikit lebih lama untuk dimuat.",
@ -213,16 +192,10 @@
"This channel does not exist.": "Kanal ini tidak ada.", "This channel does not exist.": "Kanal ini tidak ada.",
"Could not get channel info.": "Tidak bisa mendapatkan info kanal.", "Could not get channel info.": "Tidak bisa mendapatkan info kanal.",
"Could not fetch comments": "Tidak dapat memuat komentar", "Could not fetch comments": "Tidak dapat memuat komentar",
"View `x` replies": { "comments_view_x_replies_0": "Lihat {{count}} balasan",
"([^.,0-9]|^)1([^.,0-9]|$)": "Lihat`x` balasan",
"": "Lihat `x` balasan"
},
"`x` ago": "`x` lalu", "`x` ago": "`x` lalu",
"Load more": "Muat lebih banyak", "Load more": "Muat lebih banyak",
"`x` points": { "comments_points_count_0": "{{count}} poin",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` poin",
"": "`x` poin"
},
"Could not create mix.": "Tidak dapat membuat mix.", "Could not create mix.": "Tidak dapat membuat mix.",
"Empty playlist": "Daftar putar kosong", "Empty playlist": "Daftar putar kosong",
"Not a playlist.": "Bukan daftar putar.", "Not a playlist.": "Bukan daftar putar.",
@ -340,34 +313,13 @@
"Yiddish": "Bahasa Yiddi", "Yiddish": "Bahasa Yiddi",
"Yoruba": "Bahasa Yoruba", "Yoruba": "Bahasa Yoruba",
"Zulu": "Bahasa Zulu", "Zulu": "Bahasa Zulu",
"`x` years": { "generic_count_years_0": "{{count}} tahun",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` tahun", "generic_count_months_0": "{{count}} bulan",
"": "`x` tahun" "generic_count_weeks_0": "{{count}} pekan",
}, "generic_count_days_0": "{{count}} hari",
"`x` months": { "generic_count_hours_0": "{{count}} jam",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` bulan", "generic_count_minutes_0": "{{count}} menit",
"": "`x` bulan" "generic_count_seconds_0": "{{count}} detik",
},
"`x` weeks": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` pekan",
"": "`x` pekan"
},
"`x` days": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` hari",
"": "`x` hari"
},
"`x` hours": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` jam",
"": "`x` jam"
},
"`x` minutes": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` menit",
"": "`x` menit"
},
"`x` seconds": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` detik",
"": "`x` detik"
},
"Fallback comments: ": "Komentar alternatif: ", "Fallback comments: ": "Komentar alternatif: ",
"Popular": "Populer", "Popular": "Populer",
"Search": "Cari", "Search": "Cari",

View file

@ -1,16 +1,10 @@
{ {
"`x` subscribers": { "generic_subscribers_count": "{{count}} iscritto",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` iscritto", "generic_subscribers_count_plural": "{{count}} iscritti",
"": "`x` iscritti" "generic_videos_count": "{{count}} video",
}, "generic_videos_count_plural": "{{count}} video",
"`x` videos": { "generic_playlists_count": "{{count}} playlist",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` video", "generic_playlists_count_plural": "{{count}} playlist",
"": "`x` video"
},
"`x` playlists": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` playlist",
"": "`x` playlist"
},
"LIVE": "IN DIRETTA", "LIVE": "IN DIRETTA",
"Shared `x` ago": "Condiviso `x` fa", "Shared `x` ago": "Condiviso `x` fa",
"Unsubscribe": "Disiscriviti", "Unsubscribe": "Disiscriviti",
@ -122,22 +116,16 @@
"Subscription manager": "Gestione delle iscrizioni", "Subscription manager": "Gestione delle iscrizioni",
"Token manager": "Gestione dei gettoni", "Token manager": "Gestione dei gettoni",
"Token": "Gettone", "Token": "Gettone",
"`x` subscriptions": { "generic_subscriptions_count": "{{count}} iscrizione",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` iscrizione", "generic_subscriptions_count_plural": "{{count}} iscrizioni",
"": "`x` iscrizioni" "tokens_count": "{{count}} gettone",
}, "tokens_count_plural": "{{count}} gettoni",
"`x` tokens": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` gettone",
"": "`x` gettoni"
},
"Import/export": "Importa/esporta", "Import/export": "Importa/esporta",
"unsubscribe": "disiscriviti", "unsubscribe": "disiscriviti",
"revoke": "revoca", "revoke": "revoca",
"Subscriptions": "Iscrizioni", "Subscriptions": "Iscrizioni",
"`x` unseen notifications": { "subscriptions_unseen_notifs_count": "{{count}} notifica non visualizzata",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` notifica non visualizzata", "subscriptions_unseen_notifs_count_plural": "{{count}} notifiche non visualizzate",
"": "`x` notifiche non visualizzate"
},
"search": "Cerca", "search": "Cerca",
"Log out": "Esci", "Log out": "Esci",
"Source available here.": "Codice sorgente.", "Source available here.": "Codice sorgente.",
@ -166,10 +154,8 @@
"Whitelisted regions: ": "Regioni in lista bianca: ", "Whitelisted regions: ": "Regioni in lista bianca: ",
"Blacklisted regions: ": "Regioni in lista nera: ", "Blacklisted regions: ": "Regioni in lista nera: ",
"Shared `x`": "Condiviso `x`", "Shared `x`": "Condiviso `x`",
"`x` views": { "generic_views_count": "{{count}} visualizzazione",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` visualizzazione", "generic_views_count_plural": "{{count}} visualizzazioni",
"": "`x` visualizzazioni"
},
"Premieres in `x`": "In anteprima in `x`", "Premieres in `x`": "In anteprima in `x`",
"Premieres `x`": "In anteprima `x`", "Premieres `x`": "In anteprima `x`",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Ciao! Sembra che tu abbia disattivato JavaScript. Clicca qui per visualizzare i commenti. Considera che potrebbe volerci più tempo.", "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Ciao! Sembra che tu abbia disattivato JavaScript. Clicca qui per visualizzare i commenti. Considera che potrebbe volerci più tempo.",
@ -330,34 +316,20 @@
"Yiddish": "Yiddish", "Yiddish": "Yiddish",
"Yoruba": "Yoruba", "Yoruba": "Yoruba",
"Zulu": "Zulu", "Zulu": "Zulu",
"`x` years": { "generic_count_years": "{{count}} anno",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` anno", "generic_count_years_plural": "{{count}} anni",
"": "`x` anni" "generic_count_months": "{{count}} mese",
}, "generic_count_months_plural": "{{count}} mesi",
"`x` months": { "generic_count_weeks": "{{count}} settimana",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` mese", "generic_count_weeks_plural": "{{count}} settimane",
"": "`x` mesi" "generic_count_days": "{{count}} giorno",
}, "generic_count_days_plural": "{{count}} giorni",
"`x` weeks": { "generic_count_hours": "{{count}} ora",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` settimana", "generic_count_hours_plural": "{{count}} ore",
"": "`x` settimane" "generic_count_minutes": "{{count}} minuto",
}, "generic_count_minutes_plural": "{{count}} minuti",
"`x` days": { "generic_count_seconds": "{{count}} secondo",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` giorno", "generic_count_seconds_plural": "{{count}} secondi",
"": "`x` giorni"
},
"`x` hours": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` ora",
"": "`x` ore"
},
"`x` minutes": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` minuto",
"": "`x` minuti"
},
"`x` seconds": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` secondo",
"": "`x` secondi"
},
"Fallback comments: ": "Commenti alternativi: ", "Fallback comments: ": "Commenti alternativi: ",
"Popular": "Popolare", "Popular": "Popolare",
"Search": "Cerca", "Search": "Cerca",

View file

@ -1,16 +1,9 @@
{ {
"`x` subscribers": { "generic_views_count_0": "{{count}} 回視聴",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 人の登録者", "generic_videos_count_0": "{{count}} 個の動画",
"": "`x` 人の登録者" "generic_playlists_count_0": "{{count}} 個の再生リスト",
}, "generic_subscribers_count_0": "{{count}} 人の登録者",
"`x` videos": { "generic_subscriptions_count_0": "{{count}} 個の登録チャンネル",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 個の動画",
"": "`x` 個の動画"
},
"`x` playlists": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 個の再生リスト",
"": "`x` 個の再生リスト"
},
"LIVE": "ライブ", "LIVE": "ライブ",
"Shared `x` ago": "`x`前に共有", "Shared `x` ago": "`x`前に共有",
"Unsubscribe": "登録解除", "Unsubscribe": "登録解除",
@ -127,22 +120,12 @@
"Subscription manager": "登録チャンネルマネージャー", "Subscription manager": "登録チャンネルマネージャー",
"Token manager": "トークンマネージャー", "Token manager": "トークンマネージャー",
"Token": "トークン", "Token": "トークン",
"`x` subscriptions": { "tokens_count_0": "{{count}} 個のトークン",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 個の登録チャンネル",
"": "`x` 個の登録チャンネル"
},
"`x` tokens": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 個のトークン",
"": "`x` 個のトークン"
},
"Import/export": "インポート/エクスポート", "Import/export": "インポート/エクスポート",
"unsubscribe": "登録解除", "unsubscribe": "登録解除",
"revoke": "取り消す", "revoke": "取り消す",
"Subscriptions": "登録チャンネル", "Subscriptions": "登録チャンネル",
"`x` unseen notifications": { "subscriptions_unseen_notifs_count_0": "{{count}} 個の未読通知",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 個の未読通知",
"": "`x` 個の未読通知"
},
"search": "検索", "search": "検索",
"Log out": "ログアウト", "Log out": "ログアウト",
"Released under the AGPLv3 on Github.": "GitHub 上で AGPLv3 の元で公開されています。", "Released under the AGPLv3 on Github.": "GitHub 上で AGPLv3 の元で公開されています。",
@ -176,10 +159,6 @@
"Whitelisted regions: ": "ホワイトリストの地域: ", "Whitelisted regions: ": "ホワイトリストの地域: ",
"Blacklisted regions: ": "ブラックリストの地域: ", "Blacklisted regions: ": "ブラックリストの地域: ",
"Shared `x`": "`x`に共有", "Shared `x`": "`x`に共有",
"`x` views": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 回視聴",
"": "`x` 回視聴"
},
"Premieres in `x`": "`x`後にプレミア公開", "Premieres in `x`": "`x`後にプレミア公開",
"Premieres `x`": "`x`にプレミア公開", "Premieres `x`": "`x`にプレミア公開",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "やあ!君は JavaScript を無効にしているのかな?ここをクリックしてコメントを見れるけど、読み込みには少し時間がかかることがあるのを覚えておいてね。", "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "やあ!君は JavaScript を無効にしているのかな?ここをクリックしてコメントを見れるけど、読み込みには少し時間がかかることがあるのを覚えておいてね。",
@ -213,16 +192,10 @@
"This channel does not exist.": "このチャンネルは存在しません。", "This channel does not exist.": "このチャンネルは存在しません。",
"Could not get channel info.": "チャンネル情報を取得できませんでした。", "Could not get channel info.": "チャンネル情報を取得できませんでした。",
"Could not fetch comments": "コメントを取得できませんでした", "Could not fetch comments": "コメントを取得できませんでした",
"View `x` replies": { "comments_view_x_replies_0": "{{count}} 件の返信を見る",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 件の返信を見る",
"": "`x` 件の返信を見る"
},
"`x` ago": "`x`前", "`x` ago": "`x`前",
"Load more": "もっと読み込む", "Load more": "もっと読み込む",
"`x` points": { "comments_points_count_0": "{{count}} ポイント",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` ポイント",
"": "`x` ポイント"
},
"Could not create mix.": "ミックスを作成できませんでした。", "Could not create mix.": "ミックスを作成できませんでした。",
"Empty playlist": "空の再生リスト", "Empty playlist": "空の再生リスト",
"Not a playlist.": "再生リストではありません。", "Not a playlist.": "再生リストではありません。",
@ -340,34 +313,13 @@
"Yiddish": "イディッシュ語", "Yiddish": "イディッシュ語",
"Yoruba": "ヨルバ語", "Yoruba": "ヨルバ語",
"Zulu": "ズール語", "Zulu": "ズール語",
"`x` years": { "generic_count_years_0": "{{count}}年",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x`年", "generic_count_months_0": "{{count}}ヶ月",
"": "`x`年" "generic_count_weeks_0": "{{count}}週",
}, "generic_count_days_0": "{{count}}日",
"`x` months": { "generic_count_hours_0": "{{count}}時間",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x`ヶ月", "generic_count_minutes_0": "{{count}}分",
"": "`x`ヶ月" "generic_count_seconds_0": "{{count}}秒",
},
"`x` weeks": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x`週",
"": "`x`週"
},
"`x` days": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x`日",
"": "`x`日"
},
"`x` hours": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x`時間",
"": "`x`時間"
},
"`x` minutes": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x`分",
"": "`x`分"
},
"`x` seconds": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x`秒",
"": "`x`秒"
},
"Fallback comments: ": "フォールバック時のコメント: ", "Fallback comments: ": "フォールバック時のコメント: ",
"Popular": "人気", "Popular": "人気",
"Search": "検索", "Search": "検索",

View file

@ -81,18 +81,11 @@
"Subscribe": "구독", "Subscribe": "구독",
"Unsubscribe": "구독 취소", "Unsubscribe": "구독 취소",
"LIVE": "실시간", "LIVE": "실시간",
"`x` playlists": { "generic_views_count_0": "{{count}} 조회수",
"": "`x` 재생목록", "generic_videos_count_0": "{{count}} 동영상",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 재생목록" "generic_playlists_count_0": "{{count}} 재생목록",
}, "generic_subscribers_count_0": "{{count}} 구독자",
"`x` videos": { "generic_subscriptions_count_0": "{{count}} 구독",
"": "`x` 동영상",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 동영상"
},
"`x` subscribers": {
"": "`x` 구독자",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 구독자"
},
"playlist": "재생목록", "playlist": "재생목록",
"Korean": "한국어", "Korean": "한국어",
"Japanese": "일본어", "Japanese": "일본어",
@ -146,22 +139,12 @@
"Source available here.": "소스는 여기에서 사용할 수 있습니다.", "Source available here.": "소스는 여기에서 사용할 수 있습니다.",
"Log out": "로그아웃", "Log out": "로그아웃",
"search": "검색", "search": "검색",
"`x` unseen notifications": { "subscriptions_unseen_notifs_count_0": "{{count}} 읽지 않은 알림",
"": "`x` 읽지 않은 알림",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 읽지 않은 알림"
},
"Subscriptions": "구독", "Subscriptions": "구독",
"revoke": "철회", "revoke": "철회",
"unsubscribe": "구독 취소", "unsubscribe": "구독 취소",
"Import/export": "가져오기/내보내기", "Import/export": "가져오기/내보내기",
"`x` tokens": { "tokens_count_0": "{{count}} 토큰",
"": "`x` 토큰",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 토큰"
},
"`x` subscriptions": {
"": "`x` 구독",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 구독"
},
"Token": "토큰", "Token": "토큰",
"Token manager": "토큰 관리자", "Token manager": "토큰 관리자",
"Subscription manager": "구독 관리자", "Subscription manager": "구독 관리자",
@ -262,10 +245,7 @@
"Could not pull trending pages.": "인기 급상승 페이지를 가져올 수 없습니다.", "Could not pull trending pages.": "인기 급상승 페이지를 가져올 수 없습니다.",
"Could not create mix.": "믹스를 생성할 수 없습니다.", "Could not create mix.": "믹스를 생성할 수 없습니다.",
"`x` ago": "`x` 전", "`x` ago": "`x` 전",
"View `x` replies": { "comments_view_x_replies_0": "답글 {{count}}개 보기",
"": "답글 `x`개 보기",
"([^.,0-9]|^)1([^.,0-9]|$)": "답글 `x`개 보기"
},
"View Reddit comments": "Reddit의 댓글 보기", "View Reddit comments": "Reddit의 댓글 보기",
"Engagement: ": "약속: ", "Engagement: ": "약속: ",
"Wilson score: ": "Wilson Score: ", "Wilson score: ": "Wilson Score: ",
@ -300,10 +280,6 @@
"Shared `x`": "공유된 `x`", "Shared `x`": "공유된 `x`",
"Whitelisted regions: ": "차단되지 않은 지역: ", "Whitelisted regions: ": "차단되지 않은 지역: ",
"views": "조회수", "views": "조회수",
"`x` views": {
"": "`x` 조회수",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 조회수"
},
"Please log in": "로그인하세요", "Please log in": "로그인하세요",
"Password cannot be longer than 55 characters": "비밀번호는 55자 이하여야 합니다", "Password cannot be longer than 55 characters": "비밀번호는 55자 이하여야 합니다",
"Password cannot be empty": "비밀번호는 비워둘 수 없습니다", "Password cannot be empty": "비밀번호는 비워둘 수 없습니다",
@ -336,36 +312,15 @@
"Scottish Gaelic": "스코틀랜드 게일어", "Scottish Gaelic": "스코틀랜드 게일어",
"Popular": "인기", "Popular": "인기",
"Fallback comments: ": "대체 댓글: ", "Fallback comments: ": "대체 댓글: ",
"`x` seconds": {
"": "`x` 초",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 초"
},
"Swahili": "스와힐리어", "Swahili": "스와힐리어",
"Sundanese": "순다어", "Sundanese": "순다어",
"`x` hours": { "generic_count_years_0": "{{count}} 년",
"": "`x` 시", "generic_count_months_0": "{{count}} 월",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 시" "generic_count_weeks_0": "{{count}} 주",
}, "generic_count_days_0": "{{count}} 일",
"`x` minutes": { "generic_count_hours_0": "{{count}} 시",
"": "`x` 분", "generic_count_minutes_0": "{{count}} 분",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 분" "generic_count_seconds_0": "{{count}} 초",
},
"`x` days": {
"": "`x` 일",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 일"
},
"`x` weeks": {
"": "`x` 주",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 주"
},
"`x` months": {
"": "`x` 월",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 월"
},
"`x` years": {
"": "`x` 년",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 년"
},
"Zulu": "줄루어", "Zulu": "줄루어",
"Yoruba": "요루바어", "Yoruba": "요루바어",
"Yiddish": "이디시어", "Yiddish": "이디시어",
@ -383,10 +338,7 @@
"Tajik": "타지크어", "Tajik": "타지크어",
"Swedish": "스웨덴어", "Swedish": "스웨덴어",
"Spanish (Latin America)": "스페인어 (라틴 아메리카)", "Spanish (Latin America)": "스페인어 (라틴 아메리카)",
"`x` points": { "comments_points_count_0": "{{count}} 포인트",
"": "`x` 포인트",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 포인트"
},
"Invidious Private Feed for `x`": "`x` 에 대한 Invidious 비공개 피드", "Invidious Private Feed for `x`": "`x` 에 대한 Invidious 비공개 피드",
"Premieres `x`": "최초 공개 `x`", "Premieres `x`": "최초 공개 `x`",
"Premieres in `x`": "`x` 에 최초 공개", "Premieres in `x`": "`x` 에 최초 공개",

View file

@ -131,10 +131,8 @@
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` inscrições", "([^.,0-9]|^)1([^.,0-9]|$)": "`x` inscrições",
"": "`x` inscrições" "": "`x` inscrições"
}, },
"`x` tokens": { "tokens_count": "{{count}} token",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` tokens", "tokens_count_plural": "{{count}} tokens",
"": "Símbolos `x`"
},
"Import/export": "Importar/Exportar", "Import/export": "Importar/Exportar",
"unsubscribe": "cancelar inscrição", "unsubscribe": "cancelar inscrição",
"revoke": "revogar", "revoke": "revogar",
@ -340,34 +338,20 @@
"Yiddish": "Iídiche", "Yiddish": "Iídiche",
"Yoruba": "Iorubá", "Yoruba": "Iorubá",
"Zulu": "Zulu", "Zulu": "Zulu",
"`x` years": { "generic_count_years": "{{count}} ano",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` ano", "generic_count_years_plural": "{{count}} anos",
"": "`x` anos" "generic_count_months": "{{count}} mês",
}, "generic_count_months_plural": "{{count}} meses",
"`x` months": { "generic_count_weeks": "{{count}} semana",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` mês", "generic_count_weeks_plural": "{{count}} semanas",
"": "`x` meses" "generic_count_days": "{{count}} dia",
}, "generic_count_days_plural": "{{count}} dia",
"`x` weeks": { "generic_count_hours": "{{count}} hora",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` semana", "generic_count_hours_plural": "{{count}} horas",
"": "`x` semanas" "generic_count_minutes": "{{count}} minuto",
}, "generic_count_minutes_plural": "{{count}} minutos",
"`x` days": { "generic_count_seconds": "{{count}} segundo",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` dia", "generic_count_seconds_plural": "{{count}} segundos",
"": "`x` dia"
},
"`x` hours": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` hora",
"": "`x` horas"
},
"`x` minutes": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` minuto",
"": "`x` minutos"
},
"`x` seconds": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` segundo",
"": "`x` segundos"
},
"Fallback comments: ": "Comentários alternativos: ", "Fallback comments: ": "Comentários alternativos: ",
"Popular": "Populares", "Popular": "Populares",
"Search": "Procurar", "Search": "Procurar",

View file

@ -131,10 +131,8 @@
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` subscrições", "([^.,0-9]|^)1([^.,0-9]|$)": "`x` subscrições",
"": "`x` subscrições" "": "`x` subscrições"
}, },
"`x` tokens": { "tokens_count": "{{count}} token",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` tokens", "tokens_count_plural": "{{count}} tokens",
"": "`x` tokens"
},
"Import/export": "Importar / exportar", "Import/export": "Importar / exportar",
"unsubscribe": "anular subscrição", "unsubscribe": "anular subscrição",
"revoke": "revogar", "revoke": "revogar",
@ -340,34 +338,20 @@
"Yiddish": "Iídiche", "Yiddish": "Iídiche",
"Yoruba": "Ioruba", "Yoruba": "Ioruba",
"Zulu": "Zulu", "Zulu": "Zulu",
"`x` years": { "generic_count_years": "{{count}} ano",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` ano", "generic_count_years_plural": "{{count}} anos",
"": "`x` anos" "generic_count_months": "{{count}} mês",
}, "generic_count_months_plural": "{{count}} meses",
"`x` months": { "generic_count_weeks": "{{count}} seman",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` mês", "generic_count_weeks_plural": "{{count}} semanas",
"": "`x` meses" "generic_count_days": "{{count}} dia",
}, "generic_count_days_plural": "{{count}} dias",
"`x` weeks": { "generic_count_hours": "{{count}} hora",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` seman", "generic_count_hours_plural": "{{count}} horas",
"": "`x` semanas" "generic_count_minutes": "{{count}} minuto",
}, "generic_count_minutes_plural": "{{count}} minutos",
"`x` days": { "generic_count_seconds": "{{count}} segundo",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` dia", "generic_count_seconds_plural": "{{count}} segundos",
"": "`x` dias"
},
"`x` hours": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` hora",
"": "`x` horas"
},
"`x` minutes": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` minuto",
"": "`x` minutos"
},
"`x` seconds": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` segundo",
"": "`x` segundos"
},
"Fallback comments: ": "Comentários alternativos: ", "Fallback comments: ": "Comentários alternativos: ",
"Popular": "Popular", "Popular": "Popular",
"Search": "Pesquisar", "Search": "Pesquisar",

View file

@ -46,34 +46,20 @@
"Default": "Predefinido", "Default": "Predefinido",
"Top": "Destaques", "Top": "Destaques",
"Search": "Pesquisar", "Search": "Pesquisar",
"`x` seconds": { "generic_count_years": "{{count}} segundo",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` segundo", "generic_count_years_plural": "{{count}} segundos",
"": "`x` segundos" "generic_count_months": "{{count}} minuto",
}, "generic_count_months_plural": "{{count}} minutos",
"`x` minutes": { "generic_count_weeks": "{{count}} hora",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` minuto", "generic_count_weeks_plural": "{{count}} horas",
"": "`x` minutos" "generic_count_days": "{{count}} dia",
}, "generic_count_days_plural": "{{count}} dias",
"`x` hours": { "generic_count_hours": "{{count}} seman",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` hora", "generic_count_hours_plural": "{{count}} semanas",
"": "`x` horas" "generic_count_minutes": "{{count}} mês",
}, "generic_count_minutes_plural": "{{count}} meses",
"`x` days": { "generic_count_seconds": "{{count}} ano",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` dia", "generic_count_seconds_plural": "{{count}} anos",
"": "`x` dias"
},
"`x` weeks": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` seman",
"": "`x` semanas"
},
"`x` months": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` mês",
"": "`x` meses"
},
"`x` years": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` ano",
"": "`x` anos"
},
"Chinese (Traditional)": "Chinês (tradicional)", "Chinese (Traditional)": "Chinês (tradicional)",
"Chinese (Simplified)": "Chinês (simplificado)", "Chinese (Simplified)": "Chinês (simplificado)",
"Could not pull trending pages.": "Não foi possível obter as páginas de tendências.", "Could not pull trending pages.": "Não foi possível obter as páginas de tendências.",
@ -205,10 +191,8 @@
}, },
"Subscriptions": "Subscrições", "Subscriptions": "Subscrições",
"revoke": "revogar", "revoke": "revogar",
"`x` tokens": { "tokens_count": "{{count}} token",
"": "`x` tokens", "tokens_count_plural": "{{count}} tokens",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` tokens"
},
"`x` subscriptions": { "`x` subscriptions": {
"": "`x` subscrições", "": "`x` subscrições",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` subscrições" "([^.,0-9]|^)1([^.,0-9]|$)": "`x` subscrições"

View file

@ -1,11 +1,6 @@
{ {
"`x` subscribers": { "generic_videos_count_0": "{{count}} video",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` subscribers", "generic_subscribers_count_0": "{{count}} subscribers",
"": "`x` subscribers"
},
"`x` videos": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` video"
},
"LIVE": "TRỰC TIẾP", "LIVE": "TRỰC TIẾP",
"Shared `x` ago": "Đã chia sẻ` x` trước", "Shared `x` ago": "Đã chia sẻ` x` trước",
"Unsubscribe": "Hủy đăng ký", "Unsubscribe": "Hủy đăng ký",

View file

@ -1,16 +1,9 @@
{ {
"`x` subscribers": { "generic_views_count_0": "{{count}} 播放",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 位订阅者", "generic_videos_count_0": "{{count}} 个视频",
"": "`x` 位订阅者" "generic_playlists_count_0": "{{count}} 个播放列表",
}, "generic_subscribers_count_0": "{{count}} 位订阅者",
"`x` videos": { "generic_subscriptions_count_0": "{{count}} 个订阅",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 个视频",
"": "`x` 个视频"
},
"`x` playlists": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 个播放列表",
"": "`x` 个播放列表"
},
"LIVE": "直播", "LIVE": "直播",
"Shared `x` ago": "`x` 前分享", "Shared `x` ago": "`x` 前分享",
"Unsubscribe": "取消订阅", "Unsubscribe": "取消订阅",
@ -127,22 +120,12 @@
"Subscription manager": "订阅管理器", "Subscription manager": "订阅管理器",
"Token manager": "令牌管理器", "Token manager": "令牌管理器",
"Token": "令牌", "Token": "令牌",
"`x` subscriptions": { "tokens_count_0": "{{count}} 个令牌",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 个订阅",
"": "`x` 个订阅"
},
"`x` tokens": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 个令牌",
"": "`x` 个令牌"
},
"Import/export": "导入/导出", "Import/export": "导入/导出",
"unsubscribe": "取消订阅", "unsubscribe": "取消订阅",
"revoke": "吊销", "revoke": "吊销",
"Subscriptions": "订阅", "Subscriptions": "订阅",
"`x` unseen notifications": { "subscriptions_unseen_notifs_count_0": "{{count}} 条未读通知",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 条未读通知",
"": "`x` 条未读通知"
},
"search": "搜索", "search": "搜索",
"Log out": "登出", "Log out": "登出",
"Released under the AGPLv3 on Github.": "依据 AGPLv3 许可证发布于 Github。", "Released under the AGPLv3 on Github.": "依据 AGPLv3 许可证发布于 Github。",
@ -176,10 +159,6 @@
"Whitelisted regions: ": "白名单地区: ", "Whitelisted regions: ": "白名单地区: ",
"Blacklisted regions: ": "黑名单地区: ", "Blacklisted regions: ": "黑名单地区: ",
"Shared `x`": "`x`发布", "Shared `x`": "`x`发布",
"`x` views": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 播放",
"": "`x` 次观看"
},
"Premieres in `x`": "首映于 `x` 后", "Premieres in `x`": "首映于 `x` 后",
"Premieres `x`": "首映于 `x`", "Premieres `x`": "首映于 `x`",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "你好!看起来你关闭了 JavaScript。点击这里阅读评论。注意它们加载的时间可能会稍长。", "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "你好!看起来你关闭了 JavaScript。点击这里阅读评论。注意它们加载的时间可能会稍长。",
@ -213,16 +192,10 @@
"This channel does not exist.": "频道不存在。", "This channel does not exist.": "频道不存在。",
"Could not get channel info.": "无法获取频道信息。", "Could not get channel info.": "无法获取频道信息。",
"Could not fetch comments": "无法获取评论", "Could not fetch comments": "无法获取评论",
"View `x` replies": { "comments_view_x_replies_0": "查看 {{count}} 条回复",
"([^.,0-9]|^)1([^.,0-9]|$)": "查看 `x` 条回复",
"": "查看 `x` 条回复"
},
"`x` ago": "`x` 前", "`x` ago": "`x` 前",
"Load more": "加载更多", "Load more": "加载更多",
"`x` points": { "comments_points_count_0": "{{count}} 分",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 分",
"": "`x` 分"
},
"Could not create mix.": "无法创建合集。", "Could not create mix.": "无法创建合集。",
"Empty playlist": "空播放列表", "Empty playlist": "空播放列表",
"Not a playlist.": "非播放列表。", "Not a playlist.": "非播放列表。",
@ -340,34 +313,13 @@
"Yiddish": "意第绪语", "Yiddish": "意第绪语",
"Yoruba": "约鲁巴语", "Yoruba": "约鲁巴语",
"Zulu": "祖鲁语", "Zulu": "祖鲁语",
"`x` years": { "generic_count_years_0": "{{count}} 年",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 年", "generic_count_months_0": "{{count}} 月",
"": "`x` 年" "generic_count_weeks_0": "{{count}} 周",
}, "generic_count_days_0": "{{count}} 天",
"`x` months": { "generic_count_hours_0": "{{count}} 小时",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 月", "generic_count_minutes_0": "{{count}} 分钟",
"": "`x` 个月" "generic_count_seconds_0": "{{count}} 秒",
},
"`x` weeks": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 周",
"": "`x` 周"
},
"`x` days": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 天",
"": "`x` 天"
},
"`x` hours": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 小时",
"": "`x` 小时"
},
"`x` minutes": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 分钟",
"": "`x` 分钟"
},
"`x` seconds": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 秒",
"": "`x` 秒"
},
"Fallback comments: ": "后备评论: ", "Fallback comments: ": "后备评论: ",
"Popular": "热门频道", "Popular": "热门频道",
"Search": "搜索", "Search": "搜索",

View file

@ -1,16 +1,9 @@
{ {
"`x` subscribers": { "generic_views_count_0": "{{count}} 次檢視",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 個訂閱者", "generic_videos_count_0": "{{count}} 部影片",
"": "`x` 個訂閱者" "generic_playlists_count_0": "{{count}} 播放清單",
}, "generic_subscribers_count_0": "{{count}} 個訂閱者",
"`x` videos": { "generic_subscriptions_count_0": "{{count}} 個訂閱",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 部影片",
"": "`x` 部影片"
},
"`x` playlists": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 播放清單",
"": "`x` 播放清單"
},
"LIVE": "直播", "LIVE": "直播",
"Shared `x` ago": "`x` 前分享", "Shared `x` ago": "`x` 前分享",
"Unsubscribe": "取消訂閱", "Unsubscribe": "取消訂閱",
@ -127,22 +120,12 @@
"Subscription manager": "訂閱管理員", "Subscription manager": "訂閱管理員",
"Token manager": "Token 管理員", "Token manager": "Token 管理員",
"Token": "Token", "Token": "Token",
"`x` subscriptions": { "tokens_count_0": "{{count}} 個存取金鑰",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 個訂閱",
"": "`x` 個訂閱"
},
"`x` tokens": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` token",
"": "`x` 個存取金鑰"
},
"Import/export": "匯入/匯出", "Import/export": "匯入/匯出",
"unsubscribe": "取消訂閱", "unsubscribe": "取消訂閱",
"revoke": "撤銷", "revoke": "撤銷",
"Subscriptions": "訂閱", "Subscriptions": "訂閱",
"`x` unseen notifications": { "subscriptions_unseen_notifs_count_0": "{{count}} 個未讀的通知",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 個未讀的通知",
"": "`x` 個未讀的通知"
},
"search": "搜尋", "search": "搜尋",
"Log out": "登出", "Log out": "登出",
"Released under the AGPLv3 on Github.": "在 GitHub 上以 AGPLv3 釋出。", "Released under the AGPLv3 on Github.": "在 GitHub 上以 AGPLv3 釋出。",
@ -176,10 +159,6 @@
"Whitelisted regions: ": "白名單區域: ", "Whitelisted regions: ": "白名單區域: ",
"Blacklisted regions: ": "黑名單區域: ", "Blacklisted regions: ": "黑名單區域: ",
"Shared `x`": "`x` 發佈", "Shared `x`": "`x` 發佈",
"`x` views": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 次檢視",
"": "`x` 次檢視"
},
"Premieres in `x`": "首映於 `x`", "Premieres in `x`": "首映於 `x`",
"Premieres `x`": "首映於 `x`", "Premieres `x`": "首映於 `x`",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "嗨!看來您將 JavaScript 關閉了。點擊這裡以檢視留言,請注意,它們可能需要比較長的時間載入。", "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "嗨!看來您將 JavaScript 關閉了。點擊這裡以檢視留言,請注意,它們可能需要比較長的時間載入。",
@ -213,16 +192,10 @@
"This channel does not exist.": "此頻道不存在。", "This channel does not exist.": "此頻道不存在。",
"Could not get channel info.": "無法取得頻道資訊。", "Could not get channel info.": "無法取得頻道資訊。",
"Could not fetch comments": "無法擷取留言", "Could not fetch comments": "無法擷取留言",
"View `x` replies": { "comments_view_x_replies_0": "檢視 {{count}} 則回覆",
"([^.,0-9]|^)1([^.,0-9]|$)": "檢視 `x` 則回覆",
"": "檢視 `x` 則回覆"
},
"`x` ago": "`x` 以前", "`x` ago": "`x` 以前",
"Load more": "載入更多", "Load more": "載入更多",
"`x` points": { "comments_points_count_0": "{{count}} 點",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 點",
"": "`x` 點"
},
"Could not create mix.": "無法建立混合。", "Could not create mix.": "無法建立混合。",
"Empty playlist": "空的播放清單", "Empty playlist": "空的播放清單",
"Not a playlist.": "不是播放清單。", "Not a playlist.": "不是播放清單。",
@ -340,34 +313,13 @@
"Yiddish": "意第緒語", "Yiddish": "意第緒語",
"Yoruba": "約魯巴語", "Yoruba": "約魯巴語",
"Zulu": "祖魯語", "Zulu": "祖魯語",
"`x` years": { "generic_count_years_0": "{{count}} 年",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 年", "generic_count_months_0": "{{count}} 月",
"": "`x` 年" "generic_count_weeks_0": "{{count}} 週",
}, "generic_count_days_0": "{{count}} 天",
"`x` months": { "generic_count_hours_0": "{{count}} 小時",
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 月", "generic_count_minutes_0": "{{count}} 分鐘",
"": "`x` 月" "generic_count_seconds_0": "{{count}} 秒",
},
"`x` weeks": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 週",
"": "`x` 週"
},
"`x` days": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 天",
"": "`x` 天"
},
"`x` hours": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 小時",
"": "`x` 小時"
},
"`x` minutes": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 天",
"": "`x` 分鐘"
},
"`x` seconds": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` 秒",
"": "`x` 秒"
},
"Fallback comments: ": "汰退留言: ", "Fallback comments: ": "汰退留言: ",
"Popular": "熱門頻道", "Popular": "熱門頻道",
"Search": "搜尋", "Search": "搜尋",

View file

@ -42,7 +42,7 @@ shards:
spectator: spectator:
git: https://github.com/icy-arctic-fox/spectator.git git: https://github.com/icy-arctic-fox/spectator.git
version: 0.10.3 version: 0.10.4
sqlite3: sqlite3:
git: https://github.com/crystal-lang/crystal-sqlite3.git git: https://github.com/crystal-lang/crystal-sqlite3.git

View file

@ -28,10 +28,11 @@ dependencies:
athena-negotiation: athena-negotiation:
github: athena-framework/negotiation github: athena-framework/negotiation
version: ~> 0.1.1 version: ~> 0.1.1
development_dependencies: development_dependencies:
spectator: spectator:
github: icy-arctic-fox/spectator github: icy-arctic-fox/spectator
version: ~> 0.10.3 version: ~> 0.10.4
crystal: ">= 1.0.0, < 2.0.0" crystal: ">= 1.0.0, < 2.0.0"

View file

@ -0,0 +1,214 @@
require "spectator"
require "../src/invidious/helpers/i18next.cr"
Spectator.configure do |config|
config.fail_blank
config.randomize
end
def resolver
I18next::Plurals::RESOLVER
end
FORM_TESTS = {
"ach" => I18next::Plurals::PluralForms::Single_gt_one,
"ar" => I18next::Plurals::PluralForms::Special_Arabic,
"be" => I18next::Plurals::PluralForms::Dual_Slavic,
"cy" => I18next::Plurals::PluralForms::Special_Welsh,
"en" => I18next::Plurals::PluralForms::Single_not_one,
"fr" => I18next::Plurals::PluralForms::Single_gt_one,
"ga" => I18next::Plurals::PluralForms::Special_Irish,
"gd" => I18next::Plurals::PluralForms::Special_Scottish_Gaelic,
"he" => I18next::Plurals::PluralForms::Special_Hebrew,
"is" => I18next::Plurals::PluralForms::Special_Icelandic,
"jv" => I18next::Plurals::PluralForms::Special_Javanese,
"kw" => I18next::Plurals::PluralForms::Special_Cornish,
"lt" => I18next::Plurals::PluralForms::Special_Lithuanian,
"lv" => I18next::Plurals::PluralForms::Special_Latvian,
"mk" => I18next::Plurals::PluralForms::Special_Macedonian,
"mnk" => I18next::Plurals::PluralForms::Special_Mandinka,
"mt" => I18next::Plurals::PluralForms::Special_Maltese,
"or" => I18next::Plurals::PluralForms::Special_Odia,
"pl" => I18next::Plurals::PluralForms::Special_Polish_Kashubian,
"pt" => I18next::Plurals::PluralForms::Single_gt_one,
"pt-PT" => I18next::Plurals::PluralForms::Single_not_one,
"pt-BR" => I18next::Plurals::PluralForms::Single_gt_one,
"ro" => I18next::Plurals::PluralForms::Special_Romanian,
"su" => I18next::Plurals::PluralForms::None,
"sk" => I18next::Plurals::PluralForms::Special_Czech_Slovak,
"sl" => I18next::Plurals::PluralForms::Special_Slovenian,
}
SUFFIX_TESTS = {
"ach" => [
{num: 0, suffix: ""},
{num: 1, suffix: ""},
{num: 10, suffix: "_plural"},
],
"ar" => [
{num: 0, suffix: "_0"},
{num: 1, suffix: "_1"},
{num: 2, suffix: "_2"},
{num: 3, suffix: "_3"},
{num: 4, suffix: "_3"},
{num: 104, suffix: "_3"},
{num: 11, suffix: "_4"},
{num: 99, suffix: "_4"},
{num: 199, suffix: "_4"},
{num: 100, suffix: "_5"},
],
"be" => [
{num: 0, suffix: "_2"},
{num: 1, suffix: "_0"},
{num: 5, suffix: "_2"},
],
"cy" => [
{num: 0, suffix: "_2"},
{num: 1, suffix: "_0"},
{num: 3, suffix: "_2"},
{num: 8, suffix: "_3"},
],
"en" => [
{num: 0, suffix: "_plural"},
{num: 1, suffix: ""},
{num: 10, suffix: "_plural"},
],
"fr" => [
{num: 0, suffix: ""},
{num: 1, suffix: ""},
{num: 10, suffix: "_plural"},
],
"ga" => [
{num: 1, suffix: "_0"},
{num: 2, suffix: "_1"},
{num: 3, suffix: "_2"},
{num: 7, suffix: "_3"},
{num: 11, suffix: "_4"},
],
"gd" => [
{num: 1, suffix: "_0"},
{num: 2, suffix: "_1"},
{num: 3, suffix: "_2"},
{num: 20, suffix: "_3"},
],
"he" => [
{num: 0, suffix: "_3"},
{num: 1, suffix: "_0"},
{num: 2, suffix: "_1"},
{num: 3, suffix: "_3"},
{num: 20, suffix: "_2"},
{num: 21, suffix: "_3"},
{num: 30, suffix: "_2"},
{num: 100, suffix: "_2"},
{num: 101, suffix: "_3"},
],
"is" => [
{num: 1, suffix: ""},
{num: 2, suffix: "_plural"},
],
"jv" => [
{num: 0, suffix: "_0"},
{num: 1, suffix: "_1"},
],
"kw" => [
{num: 1, suffix: "_0"},
{num: 2, suffix: "_1"},
{num: 3, suffix: "_2"},
{num: 4, suffix: "_3"},
],
"lt" => [
{num: 1, suffix: "_0"},
{num: 2, suffix: "_1"},
{num: 10, suffix: "_2"},
],
"lv" => [
{num: 1, suffix: "_0"},
{num: 2, suffix: "_1"},
{num: 0, suffix: "_2"},
],
"mk" => [
{num: 1, suffix: ""},
{num: 2, suffix: "_plural"},
{num: 0, suffix: "_plural"},
{num: 11, suffix: "_plural"},
{num: 21, suffix: ""},
{num: 31, suffix: ""},
{num: 311, suffix: "_plural"},
],
"mnk" => [
{num: 0, suffix: "_0"},
{num: 1, suffix: "_1"},
{num: 2, suffix: "_2"},
],
"mt" => [
{num: 1, suffix: "_0"},
{num: 2, suffix: "_1"},
{num: 11, suffix: "_2"},
{num: 20, suffix: "_3"},
],
"or" => [
{num: 2, suffix: "_1"},
{num: 1, suffix: "_0"},
],
"pl" => [
{num: 0, suffix: "_2"},
{num: 1, suffix: "_0"},
{num: 5, suffix: "_2"},
],
"pt" => [
{num: 0, suffix: ""},
{num: 1, suffix: ""},
{num: 10, suffix: "_plural"},
],
"pt-PT" => [
{num: 0, suffix: "_plural"},
{num: 1, suffix: ""},
{num: 10, suffix: "_plural"},
],
"pt-BR" => [
{num: 0, suffix: ""},
{num: 1, suffix: ""},
{num: 10, suffix: "_plural"},
],
"ro" => [
{num: 0, suffix: "_1"},
{num: 1, suffix: "_0"},
{num: 20, suffix: "_2"},
],
"su" => [
{num: 0, suffix: "_0"},
{num: 1, suffix: "_0"},
{num: 10, suffix: "_0"},
],
"sk" => [
{num: 0, suffix: "_2"},
{num: 1, suffix: "_0"},
{num: 5, suffix: "_2"},
],
"sl" => [
{num: 5, suffix: "_0"},
{num: 1, suffix: "_1"},
{num: 2, suffix: "_2"},
{num: 3, suffix: "_3"},
],
}
Spectator.describe "i18next_Plural_Resolver" do
describe "get_plural_form" do
sample FORM_TESTS do |locale, form|
it "returns the right plural form for locale '#{locale}'" do
expect(resolver.get_plural_form(locale)).to eq(form)
end
end
end
describe "get_suffix" do
sample SUFFIX_TESTS do |locale, tests|
it "returns the right suffix for locale '#{locale}'" do
tests.each do |d|
expect(resolver.get_suffix(locale, d[:num])).to eq(d[:suffix])
end
end
end
end
end

View file

@ -158,7 +158,7 @@ def fetch_channel_community(ucid, continuation, locale, format, thin_mode)
view_count = attachment["viewCountText"]?.try &.["simpleText"].as_s.gsub(/\D/, "").to_i64? || 0_i64 view_count = attachment["viewCountText"]?.try &.["simpleText"].as_s.gsub(/\D/, "").to_i64? || 0_i64
json.field "viewCount", view_count json.field "viewCount", view_count
json.field "viewCountText", translate(locale, "`x` views", number_to_short_text(view_count)) json.field "viewCountText", translate_count(locale, "generic_views_count", view_count, NumberFormatting::Short)
end end
when .has_key?("backstageImageRenderer") when .has_key?("backstageImageRenderer")
attachment = attachment["backstageImageRenderer"] attachment = attachment["backstageImageRenderer"]

View file

@ -303,13 +303,19 @@ def template_youtube_comments(comments, locale, thin_mode, is_replies = false)
root = comments["comments"].as_a root = comments["comments"].as_a
root.each do |child| root.each do |child|
if child["replies"]? if child["replies"]?
replies_count_text = translate_count(locale,
"comments_view_x_replies",
child["replies"]["replyCount"].as_s.to_i? || 0,
NumberFormatting::Separator
)
replies_html = <<-END_HTML replies_html = <<-END_HTML
<div id="replies" class="pure-g"> <div id="replies" class="pure-g">
<div class="pure-u-1-24"></div> <div class="pure-u-1-24"></div>
<div class="pure-u-23-24"> <div class="pure-u-23-24">
<p> <p>
<a href="javascript:void(0)" data-continuation="#{child["replies"]["continuation"]}" <a href="javascript:void(0)" data-continuation="#{child["replies"]["continuation"]}"
data-onclick="get_youtube_replies" data-load-replies>#{translate(locale, "View `x` replies", number_with_separator(child["replies"]["replyCount"]))}</a> data-onclick="get_youtube_replies" data-load-replies>#{replies_count_text}</a>
</p> </p>
</div> </div>
</div> </div>
@ -471,7 +477,7 @@ def template_reddit_comments(root, locale)
<p> <p>
<a href="javascript:void(0)" data-onclick="toggle_parent">[ - ]</a> <a href="javascript:void(0)" data-onclick="toggle_parent">[ - ]</a>
<b><a href="https://www.reddit.com/user/#{child.author}">#{child.author}</a></b> <b><a href="https://www.reddit.com/user/#{child.author}">#{child.author}</a></b>
#{translate(locale, "`x` points", number_with_separator(child.score))} #{translate_count(locale, "comments_points_count", child.score, NumberFormatting::Separator)}
<span title="#{child.created_utc.to_s(translate(locale, "%a %B %-d %T %Y UTC"))}">#{translate(locale, "`x` ago", recode_date(child.created_utc, locale))}</span> <span title="#{child.created_utc.to_s(translate(locale, "%a %B %-d %T %Y UTC"))}">#{translate(locale, "`x` ago", recode_date(child.created_utc, locale))}</span>
<a href="https://www.reddit.com#{child.permalink}" title="#{translate(locale, "permalink")}">#{translate(locale, "permalink")}</a> <a href="https://www.reddit.com#{child.permalink}" title="#{translate(locale, "permalink")}">#{translate(locale, "permalink")}</a>
</p> </p>

View file

@ -54,6 +54,14 @@ CONTENT_REGIONS = {
"YE", "ZA", "ZW", "YE", "ZA", "ZW",
} }
# Enum for the different types of number formats
enum NumberFormatting
None # Print the number as-is
Separator # Use a separator for thousands
Short # Use short notation (k/M/B)
HtmlSpan # Surround with <span id="count"></span>
end
def load_all_locales def load_all_locales
locales = {} of String => Hash(String, JSON::Any) locales = {} of String => Hash(String, JSON::Any)
@ -107,6 +115,42 @@ def translate(locale : String?, key : String, text : String | Nil = nil) : Strin
return translation return translation
end end
def translate_count(locale : String, key : String, count : Int, format = NumberFormatting::None) : String
# Fallback on english if locale doesn't exist
locale = "en-US" if !LOCALES.has_key?(locale)
# Retrieve suffix
suffix = I18next::Plurals::RESOLVER.get_suffix(locale, count)
plural_key = key + suffix
if LOCALES[locale].has_key?(plural_key)
translation = LOCALES[locale][plural_key].as_s
else
# Try #1: Fallback to singular in the same locale
singular_suffix = I18next::Plurals::RESOLVER.get_suffix(locale, 1)
if LOCALES[locale].has_key?(key + singular_suffix)
translation = LOCALES[locale][key + singular_suffix].as_s
elsif locale != "en-US"
# Try #2: Fallback to english
translation = translate_count("en-US", key, count)
else
# Return key if we're already in english, as the tranlation is missing
LOGGER.warn("i18n: Missing translation key \"#{key}\"")
return key
end
end
case format
when .separator? then count_txt = number_with_separator(count)
when .short? then count_txt = number_to_short_text(count)
when .html_span? then count_txt = "<span id=\"count\">" + count.to_s + "</span>"
else count_txt = count.to_s
end
return translation.gsub("{{count}}", count_txt)
end
def translate_bool(locale : String?, translation : Bool) def translate_bool(locale : String?, translation : Bool)
case translation case translation
when true when true

View file

@ -0,0 +1,511 @@
# I18next-compatible implementation of plural forms
#
module I18next::Plurals
# -----------------------------------
# I18next plural forms definition
# -----------------------------------
enum PluralForms
# One singular, one plural forms
Single_gt_one = 1 # E.g: French
Single_not_one = 2 # E.g: English
# No plural forms (E.g: Azerbaijani)
None = 3
# One singular, two plural forms
Dual_Slavic = 4 # E.g: Russian
# Special cases (rules used by only one or two language(s))
Special_Arabic = 5
Special_Czech_Slovak = 6
Special_Polish_Kashubian = 7
Special_Welsh = 8
Special_Irish = 10
Special_Scottish_Gaelic = 11
Special_Icelandic = 12
Special_Javanese = 13
Special_Cornish = 14
Special_Lithuanian = 15
Special_Latvian = 16
Special_Macedonian = 17
Special_Mandinka = 18
Special_Maltese = 19
Special_Romanian = 20
Special_Slovenian = 21
Special_Hebrew = 22
Special_Odia = 23
end
private PLURAL_SETS = {
PluralForms::Single_gt_one => [
"ach", "ak", "am", "arn", "br", "fil", "fr", "gun", "ln", "mfe", "mg",
"mi", "oc", "pt", "pt-BR", "tg", "tl", "ti", "tr", "uz", "wa",
],
PluralForms::Single_not_one => [
"af", "an", "ast", "az", "bg", "bn", "ca", "da", "de", "dev", "el", "en",
"eo", "es", "et", "eu", "fi", "fo", "fur", "fy", "gl", "gu", "ha", "hi",
"hu", "hy", "ia", "it", "kk", "kn", "ku", "lb", "mai", "ml", "mn", "mr",
"nah", "nap", "nb", "ne", "nl", "nn", "no", "nso", "pa", "pap", "pms",
"ps", "pt-PT", "rm", "sco", "se", "si", "so", "son", "sq", "sv", "sw",
"ta", "te", "tk", "ur", "yo",
],
PluralForms::None => [
"ay", "bo", "cgg", "fa", "ht", "id", "ja", "jbo", "ka", "km", "ko", "ky",
"lo", "ms", "sah", "su", "th", "tt", "ug", "vi", "wo", "zh",
],
PluralForms::Dual_Slavic => [
"be", "bs", "cnr", "dz", "hr", "ru", "sr", "uk",
],
}
private PLURAL_SINGLES = {
"ar" => PluralForms::Special_Arabic,
"cs" => PluralForms::Special_Czech_Slovak,
"csb" => PluralForms::Special_Polish_Kashubian,
"cy" => PluralForms::Special_Welsh,
"ga" => PluralForms::Special_Irish,
"gd" => PluralForms::Special_Scottish_Gaelic,
"he" => PluralForms::Special_Hebrew,
"is" => PluralForms::Special_Icelandic,
"iw" => PluralForms::Special_Hebrew,
"jv" => PluralForms::Special_Javanese,
"kw" => PluralForms::Special_Cornish,
"lt" => PluralForms::Special_Lithuanian,
"lv" => PluralForms::Special_Latvian,
"mk" => PluralForms::Special_Macedonian,
"mnk" => PluralForms::Special_Mandinka,
"mt" => PluralForms::Special_Maltese,
"or" => PluralForms::Special_Odia,
"pl" => PluralForms::Special_Polish_Kashubian,
"ro" => PluralForms::Special_Romanian,
"sk" => PluralForms::Special_Czech_Slovak,
"sl" => PluralForms::Special_Slovenian,
}
# These are the v1 and v2 compatible suffixes.
# The array indices matches the PluralForms enum above.
private NUMBERS = [
[1, 2], # 1
[1, 2], # 2
[1], # 3
[1, 2, 5], # 4
[0, 1, 2, 3, 11, 100], # 5
[1, 2, 5], # 6
[1, 2, 5], # 7
[1, 2, 3, 8], # 8
[1, 2], # 9 (not used)
[1, 2, 3, 7, 11], # 10
[1, 2, 3, 20], # 11
[1, 2], # 12
[0, 1], # 13
[1, 2, 3, 4], # 14
[1, 2, 10], # 15
[1, 2, 0], # 16
[1, 2], # 17
[0, 1, 2], # 18
[1, 2, 11, 20], # 19
[1, 2, 20], # 20
[5, 1, 2, 3], # 21
[1, 2, 20, 21], # 22
[2, 1], # 23 (Odia)
]
# -----------------------------------
# I18next plural resolver class
# -----------------------------------
RESOLVER = Resolver.new
class Resolver
private property forms = {} of String => PluralForms
property version : UInt8 = 3
# Options
property simplify_plural_suffix : Bool = true
def initialize(version : Int = 3)
# Sanity checks
# V4 isn't supported, as it requires a full CLDR database.
if version > 4 || version == 0
raise "Invalid i18next version: v#{version}."
elsif version == 4
# Logger.error("Unsupported i18next version: v4. Falling back to v3")
@version = 3_u8
else
@version = version.to_u8
end
self.init_rules
end
def init_rules
# Look into sets
PLURAL_SETS.each do |form, langs|
langs.each { |lang| self.forms[lang] = form }
end
# Add plurals from the "singles" set
self.forms.merge!(PLURAL_SINGLES)
end
def get_plural_form(locale : String) : PluralForms
# Extract the ISO 639-1 or 639-2 code from an RFC 5646 language code,
# except for pt-BR and pt-PT which needs to be kept as-is.
if !locale.matches?(/^pt-(BR|PT)$/)
locale = locale.split('-')[0]
end
return self.forms[locale] if self.forms[locale]?
# If nothing was found, then use the most common form, i.e
# one singular and one plural, as in english. Not perfect,
# but better than yielding an exception at the user.
return PluralForms::Single_not_one
end
def get_suffix(locale : String, count : Int) : String
# Checked count must be absolute. In i18next, `rule.noAbs` is used to
# determine if comparison should be done on a signed or unsigned integer,
# but this variable is never set, resulting in the comparison always
# being done on absolute numbers.
return get_suffix_retrocompat(locale, count.abs)
end
# Emulate the `rule.numbers.size == 2 && rule.numbers[0] == 1` check
# from original i18next code
private def is_simple_plural(form : PluralForms) : Bool
case form
when .single_gt_one? then return true
when .single_not_one? then return true
when .special_icelandic? then return true
when .special_macedonian? then return true
else
return false
end
end
private def get_suffix_retrocompat(locale : String, count : Int) : String
# Get plural form
plural_form = get_plural_form(locale)
# Languages with no plural have the "_0" suffix
return "_0" if plural_form.none?
# Get the index and suffix for this number
idx = SuffixIndex.get_index(plural_form, count)
# Simple plurals are handled differently in all versions (but v4)
if @simplify_plural_suffix && is_simple_plural(plural_form)
return (idx == 1) ? "_plural" : ""
end
# More complex plurals
# TODO: support v1 and v2
# TODO: support `options.prepend` (v2 and v3)
# this.options.prepend && suffix.toString() ? this.options.prepend + suffix.toString() : suffix.toString()
#
# case @version
# when 1
# suffix = SUFFIXES_V1_V2[plural_form.to_i][idx]
# return (suffix == 1) ? "" : return "_plural_#{suffix}"
# when 2
# return "_#{suffix}"
# else # v3
return "_#{idx}"
# end
end
end
# -----------------------------
# Plural functions
# -----------------------------
module SuffixIndex
def self.get_index(plural_form : PluralForms, count : Int) : UInt8
case plural_form
when .single_gt_one? then return (count > 1) ? 1_u8 : 0_u8
when .single_not_one? then return (count != 1) ? 1_u8 : 0_u8
when .none? then return 0_u8
when .dual_slavic? then return dual_slavic(count)
when .special_arabic? then return special_arabic(count)
when .special_czech_slovak? then return special_czech_slovak(count)
when .special_polish_kashubian? then return special_polish_kashubian(count)
when .special_welsh? then return special_welsh(count)
when .special_irish? then return special_irish(count)
when .special_scottish_gaelic? then return special_scottish_gaelic(count)
when .special_icelandic? then return special_icelandic(count)
when .special_javanese? then return special_javanese(count)
when .special_cornish? then return special_cornish(count)
when .special_lithuanian? then return special_lithuanian(count)
when .special_latvian? then return special_latvian(count)
when .special_macedonian? then return special_macedonian(count)
when .special_mandinka? then return special_mandinka(count)
when .special_maltese? then return special_maltese(count)
when .special_romanian? then return special_romanian(count)
when .special_slovenian? then return special_slovenian(count)
when .special_hebrew? then return special_hebrew(count)
when .special_odia? then return special_odia(count)
else
# default, if nothing matched above
return 0_u8
end
end
# Plural form of Slavic languages (E.g: Russian)
#
# Corresponds to i18next rule #4
# Rule: (n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)
#
def self.dual_slavic(count : Int) : UInt8
n_mod_10 = count % 10
n_mod_100 = count % 100
if n_mod_10 == 1 && n_mod_100 != 11
return 0_u8
elsif n_mod_10 >= 2 && n_mod_10 <= 4 && (n_mod_100 < 10 || n_mod_100 >= 20)
return 1_u8
else
return 2_u8
end
end
# Plural form for Arabic language
#
# Corresponds to i18next rule #5
# Rule: (n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5)
#
def self.special_arabic(count : Int) : UInt8
return count.to_u8 if (count == 0 || count == 1 || count == 2)
n_mod_100 = count % 100
return 3_u8 if (n_mod_100 >= 3 && n_mod_100 <= 10)
return 4_u8 if (n_mod_100 >= 11)
return 5_u8
end
# Plural form for Czech and Slovak languages
#
# Corresponds to i18next rule #6
# Rule: ((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2)
#
def self.special_czech_slovak(count : Int) : UInt8
return 0_u8 if (count == 1)
return 1_u8 if (count >= 2 && count <= 4)
return 2_u8
end
# Plural form for Polish and Kashubian languages
#
# Corresponds to i18next rule #7
# Rule: (n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)
#
def self.special_polish_kashubian(count : Int) : UInt8
return 0_u8 if (count == 1)
n_mod_10 = count % 10
n_mod_100 = count % 100
if n_mod_10 >= 2 && n_mod_10 <= 4 && (n_mod_100 < 10 || n_mod_100 >= 20)
return 1_u8
else
return 2_u8
end
end
# Plural form for Welsh language
#
# Corresponds to i18next rule #8
# Rule: ((n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3)
#
def self.special_welsh(count : Int) : UInt8
return 0_u8 if (count == 1)
return 1_u8 if (count == 2)
return 2_u8 if (count != 8 && count != 11)
return 3_u8
end
# Plural form for Irish language
#
# Corresponds to i18next rule #10
# Rule: (n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4)
#
def self.special_irish(count : Int) : UInt8
return 0_u8 if (count == 1)
return 1_u8 if (count == 2)
return 2_u8 if (count < 7)
return 3_u8 if (count < 11)
return 4_u8
end
# Plural form for Gaelic language
#
# Corresponds to i18next rule #11
# Rule: ((n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3)
#
def self.special_scottish_gaelic(count : Int) : UInt8
return 0_u8 if (count == 1 || count == 11)
return 1_u8 if (count == 2 || count == 12)
return 2_u8 if (count > 2 && count < 20)
return 3_u8
end
# Plural form for Icelandic language
#
# Corresponds to i18next rule #12
# Rule: (n%10!=1 || n%100==11)
#
def self.special_icelandic(count : Int) : UInt8
if (count % 10) != 1 || (count % 100) == 11
return 1_u8
else
return 0_u8
end
end
# Plural form for Javanese language
#
# Corresponds to i18next rule #13
# Rule: (n !== 0)
#
def self.special_javanese(count : Int) : UInt8
return (count != 0) ? 1_u8 : 0_u8
end
# Plural form for Cornish language
#
# Corresponds to i18next rule #14
# Rule: ((n==1) ? 0 : (n==2) ? 1 : (n == 3) ? 2 : 3)
#
def self.special_cornish(count : Int) : UInt8
return 0_u8 if count == 1
return 1_u8 if count == 2
return 2_u8 if count == 3
return 3_u8
end
# Plural form for Lithuanian language
#
# Corresponds to i18next rule #15
# Rule: (n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2)
#
def self.special_lithuanian(count : Int) : UInt8
n_mod_10 = count % 10
n_mod_100 = count % 100
if n_mod_10 == 1 && n_mod_100 != 11
return 0_u8
elsif n_mod_10 >= 2 && (n_mod_100 < 10 || n_mod_100 >= 20)
return 1_u8
else
return 2_u8
end
end
# Plural form for Latvian language
#
# Corresponds to i18next rule #16
# Rule: (n%10==1 && n%100!=11 ? 0 : n !== 0 ? 1 : 2)
#
def self.special_latvian(count : Int) : UInt8
if (count % 10) == 1 && (count % 100) != 11
return 0_u8
elsif count != 0
return 1_u8
else
return 2_u8
end
end
# Plural form for Macedonian language
#
# Corresponds to i18next rule #17
# Rule: (n==1 || n%10==1 && n%100!=11 ? 0 : 1)
#
def self.special_macedonian(count : Int) : UInt8
if count == 1 || ((count % 10) == 1 && (count % 100) != 11)
return 0_u8
else
return 1_u8
end
end
# Plural form for Mandinka language
#
# Corresponds to i18next rule #18
# Rule: (n==0 ? 0 : n==1 ? 1 : 2)
#
def self.special_mandinka(count : Int) : UInt8
return (count == 0 || count == 1) ? count.to_u8 : 2_u8
end
# Plural form for Maltese language
#
# Corresponds to i18next rule #19
# Rule: (n==1 ? 0 : n==0 || ( n%100>1 && n%100<11) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3)
#
def self.special_maltese(count : Int) : UInt8
return 0_u8 if count == 1
return 1_u8 if count == 0
n_mod_100 = count % 100
return 1_u8 if (n_mod_100 > 1 && n_mod_100 < 11)
return 2_u8 if (n_mod_100 > 10 && n_mod_100 < 20)
return 3_u8
end
# Plural form for Romanian language
#
# Corresponds to i18next rule #20
# Rule: (n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2)
#
def self.special_romanian(count : Int) : UInt8
return 0_u8 if count == 1
return 1_u8 if count == 0
n_mod_100 = count % 100
return 1_u8 if (n_mod_100 > 0 && n_mod_100 < 20)
return 2_u8
end
# Plural form for Slovenian language
#
# Corresponds to i18next rule #21
# Rule: (n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0)
#
def self.special_slovenian(count : Int) : UInt8
n_mod_100 = count % 100
return 1_u8 if (n_mod_100 == 1)
return 2_u8 if (n_mod_100 == 2)
return 3_u8 if (n_mod_100 == 3 || n_mod_100 == 4)
return 0_u8
end
# Plural form for Hebrew language
#
# Corresponds to i18next rule #22
# Rule: (n==1 ? 0 : n==2 ? 1 : (n<0 || n>10) && n%10==0 ? 2 : 3)
#
def self.special_hebrew(count : Int) : UInt8
return 0_u8 if (count == 1)
return 1_u8 if (count == 2)
if (count < 0 || count > 10) && (count % 10) == 0
return 2_u8
else
return 3_u8
end
end
# Plural form for Odia ("or") language
#
# This one is a bit special. It should use rule #2 (like english)
# but the "numbers" (suffixes?) it has are inverted, so we'll make a
# special rule for it.
#
def self.special_odia(count : Int) : UInt8
return (count == 1) ? 0_u8 : 1_u8
end
end
end

View file

@ -123,22 +123,20 @@ def recode_date(time : Time, locale)
span = Time.utc - time span = Time.utc - time
if span.total_days > 365.0 if span.total_days > 365.0
span = translate(locale, "`x` years", (span.total_days.to_i // 365).to_s) return translate_count(locale, "generic_count_years", span.total_days.to_i // 365)
elsif span.total_days > 30.0 elsif span.total_days > 30.0
span = translate(locale, "`x` months", (span.total_days.to_i // 30).to_s) return translate_count(locale, "generic_count_months", span.total_days.to_i // 30)
elsif span.total_days > 7.0 elsif span.total_days > 7.0
span = translate(locale, "`x` weeks", (span.total_days.to_i // 7).to_s) return translate_count(locale, "generic_count_weeks", span.total_days.to_i // 7)
elsif span.total_hours > 24.0 elsif span.total_hours > 24.0
span = translate(locale, "`x` days", (span.total_days.to_i).to_s) return translate_count(locale, "generic_count_days", span.total_days.to_i)
elsif span.total_minutes > 60.0 elsif span.total_minutes > 60.0
span = translate(locale, "`x` hours", (span.total_hours.to_i).to_s) return translate_count(locale, "generic_count_hours", span.total_hours.to_i)
elsif span.total_seconds > 60.0 elsif span.total_seconds > 60.0
span = translate(locale, "`x` minutes", (span.total_minutes.to_i).to_s) return translate_count(locale, "generic_count_minutes", span.total_minutes.to_i)
else else
span = translate(locale, "`x` seconds", (span.total_seconds.to_i).to_s) return translate_count(locale, "generic_count_seconds", span.total_seconds.to_i)
end end
return span
end end
def number_with_separator(number) def number_with_separator(number)

View file

@ -10,8 +10,8 @@
<% end %> <% end %>
<p dir="auto"><%= HTML.escape(item.author) %></p> <p dir="auto"><%= HTML.escape(item.author) %></p>
</a> </a>
<p><%= translate(locale, "`x` subscribers", number_with_separator(item.subscriber_count)) %></p> <p><%= translate_count(locale, "generic_subscribers_count", item.subscriber_count, NumberFormatting::Separator) %></p>
<% if !item.auto_generated %><p><%= translate(locale, "`x` videos", number_with_separator(item.video_count)) %></p><% end %> <% if !item.auto_generated %><p><%= translate_count(locale, "generic_videos_count", item.video_count, NumberFormatting::Separator) %></p><% end %>
<h5><%= item.description_html %></h5> <h5><%= item.description_html %></h5>
<% when SearchPlaylist, InvidiousPlaylist %> <% when SearchPlaylist, InvidiousPlaylist %>
<% if item.id.starts_with? "RD" %> <% if item.id.starts_with? "RD" %>
@ -24,7 +24,7 @@
<% if !env.get("preferences").as(Preferences).thin_mode %> <% if !env.get("preferences").as(Preferences).thin_mode %>
<div class="thumbnail"> <div class="thumbnail">
<img loading="lazy" class="thumbnail" src="<%= URI.parse(item.thumbnail || "/").request_target %>"/> <img loading="lazy" class="thumbnail" src="<%= URI.parse(item.thumbnail || "/").request_target %>"/>
<p class="length"><%= number_with_separator(item.video_count) %> videos</p> <p class="length"><%= translate_count(locale, "generic_videos_count", item.video_count, NumberFormatting::Separator) %></p>
</div> </div>
<% end %> <% end %>
<p dir="auto"><%= HTML.escape(item.title) %></p> <p dir="auto"><%= HTML.escape(item.title) %></p>
@ -94,7 +94,7 @@
<% if item.responds_to?(:views) && item.views %> <% if item.responds_to?(:views) && item.views %>
<div class="flex-right"> <div class="flex-right">
<p dir="auto"><%= translate(locale, "`x` views", number_to_short_text(item.views || 0)) %></p> <p dir="auto"><%= translate_count(locale, "generic_views_count", item.views || 0, NumberFormatting::Short) %></p>
</div> </div>
<% end %> <% end %>
</div> </div>
@ -160,7 +160,7 @@
<% if item.responds_to?(:views) && item.views %> <% if item.responds_to?(:views) && item.views %>
<div class="flex-right"> <div class="flex-right">
<p class="video-data" dir="auto"><%= translate(locale, "`x` views", number_to_short_text(item.views || 0)) %></p> <p class="video-data" dir="auto"><%= translate_count(locale, "generic_views_count", item.views || 0, NumberFormatting::Short) %></p>
</div> </div>
<% end %> <% end %>
</div> </div>

View file

@ -11,7 +11,7 @@
<h3><input class="pure-input-1" maxlength="150" name="title" type="text" value="<%= title %>"></h3> <h3><input class="pure-input-1" maxlength="150" name="title" type="text" value="<%= title %>"></h3>
<b> <b>
<%= HTML.escape(playlist.author) %> | <%= HTML.escape(playlist.author) %> |
<%= translate(locale, "`x` videos", "#{playlist.video_count}") %> | <%= translate_count(locale, "generic_videos_count", playlist.video_count) %> |
<%= translate(locale, "Updated `x` ago", recode_date(playlist.updated, locale)) %> | <%= translate(locale, "Updated `x` ago", recode_date(playlist.updated, locale)) %> |
<i class="icon <%= {"ion-md-globe", "ion-ios-unlock", "ion-ios-lock"}[playlist.privacy.value] %>"></i> <i class="icon <%= {"ion-md-globe", "ion-ios-unlock", "ion-ios-lock"}[playlist.privacy.value] %>"></i>
<select name="privacy"> <select name="privacy">

View file

@ -4,11 +4,11 @@
<div class="pure-g h-box"> <div class="pure-g h-box">
<div class="pure-u-1-3"> <div class="pure-u-1-3">
<h3><%= translate(locale, "`x` videos", %(<span id="count">#{user.watched.size}</span>)) %></h3> <h3><%= translate_count(locale, "generic_videos_count", user.watched.size, NumberFormatting::HtmlSpan) %></h3>
</div> </div>
<div class="pure-u-1-3"> <div class="pure-u-1-3">
<h3 style="text-align:center"> <h3 style="text-align:center">
<a href="/feed/subscriptions"><%= translate(locale, "`x` subscriptions", %(<span id="count">#{user.subscriptions.size}</span>)) %></a> <a href="/feed/subscriptions"><%= translate_count(locale, "generic_subscriptions_count", user.subscriptions.size, NumberFormatting::HtmlSpan) %></a>
</h3> </h3>
</div> </div>
<div class="pure-u-1-3"> <div class="pure-u-1-3">

View file

@ -24,7 +24,7 @@
</div> </div>
<center> <center>
<%= translate(locale, "`x` unseen notifications", "#{notifications.size}") %> <%= translate_count(locale, "subscriptions_unseen_notifs_count", notifications.size) %>
</center> </center>
<% if !notifications.empty? %> <% if !notifications.empty? %>

View file

@ -16,7 +16,7 @@
<% else %> <% else %>
<%= author %> | <%= author %> |
<% end %> <% end %>
<%= translate(locale, "`x` videos", "#{playlist.video_count}") %> | <%= translate_count(locale, "generic_videos_count", playlist.video_count) %> |
<%= translate(locale, "Updated `x` ago", recode_date(playlist.updated, locale)) %> | <%= translate(locale, "Updated `x` ago", recode_date(playlist.updated, locale)) %> |
<% case playlist.as(InvidiousPlaylist).privacy when %> <% case playlist.as(InvidiousPlaylist).privacy when %>
<% when PlaylistPrivacy::Public %> <% when PlaylistPrivacy::Public %>
@ -30,7 +30,7 @@
<% else %> <% else %>
<b> <b>
<a href="/channel/<%= playlist.ucid %>"><%= author %></a> | <a href="/channel/<%= playlist.ucid %>"><%= author %></a> |
<%= translate(locale, "`x` videos", "#{playlist.video_count}") %> | <%= translate_count(locale, "generic_videos_count", playlist.video_count) %> |
<%= translate(locale, "Updated `x` ago", recode_date(playlist.updated, locale)) %> <%= translate(locale, "Updated `x` ago", recode_date(playlist.updated, locale)) %>
</b> </b>
<% end %> <% end %>

View file

@ -6,7 +6,7 @@
<div class="pure-u-1-3"> <div class="pure-u-1-3">
<h3> <h3>
<a href="/feed/subscriptions"> <a href="/feed/subscriptions">
<%= translate(locale, "`x` subscriptions", %(<span id="count">#{subscriptions.size}</span>)) %> <%= translate_count(locale, "generic_subscriptions_count", subscriptions.size, NumberFormatting::HtmlSpan) %>
</a> </a>
</h3> </h3>
</div> </div>

View file

@ -5,7 +5,7 @@
<div class="pure-g h-box"> <div class="pure-g h-box">
<div class="pure-u-1-3"> <div class="pure-u-1-3">
<h3> <h3>
<%= translate(locale, "`x` tokens", %(<span id="count">#{tokens.size}</span>)) %> <%= translate_count(locale, "tokens_count", tokens.size, NumberFormatting::HtmlSpan) %>
</h3> </h3>
</div> </div>
<div class="pure-u-1-3"></div> <div class="pure-u-1-3"></div>

View file

@ -323,7 +323,7 @@ we're going to need to do it here in order to allow for translations.
<div class="pure-u-10-24" style="text-align:right"> <div class="pure-u-10-24" style="text-align:right">
<% if views = rv["short_view_count_text"]?.try &.delete(", views watching") %> <% if views = rv["short_view_count_text"]?.try &.delete(", views watching") %>
<% if !views.empty? %> <% if !views.empty? %>
<b class="width:100%"><%= translate(locale, "`x` views", views) %></b> <b class="width:100%"><%= translate_count(locale, "generic_views_count", views.to_i? || 0) %></b>
<% end %> <% end %>
<% end %> <% end %>
</div> </div>