mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-03-11 17:45:38 +00:00
added Hindi
This commit is contained in:
parent
86f6bc4ae2
commit
77f5cb2b80
15 changed files with 1476 additions and 86 deletions
|
|
@ -8,5 +8,6 @@ export const LOCALES = [
|
|||
{ code: 'it', key: 'italian' },
|
||||
{ code: 'es', key: 'spanish' },
|
||||
{ code: 'hr', key: 'croatian' },
|
||||
{ code: 'zh-CN', key: 'chinese' }
|
||||
{ code: 'zh-CN', key: 'chinese' },
|
||||
{ code: 'hi', key: 'hindi' }
|
||||
];
|
||||
|
|
@ -632,6 +632,7 @@
|
|||
"italian": "الإيطالية",
|
||||
"croatian": "الكرواتية",
|
||||
"chinese": "الصينية (المبسطة)",
|
||||
"hindi": "الهندية",
|
||||
"account": "الحساب",
|
||||
"content_discovery": "المحتوى والاكتشاف",
|
||||
"appearance": "المظهر",
|
||||
|
|
|
|||
|
|
@ -632,6 +632,7 @@
|
|||
"italian": "Italienisch",
|
||||
"croatian": "Kroatisch",
|
||||
"chinese": "Chinesisch (Vereinfacht)",
|
||||
"hindi": "Hindi",
|
||||
"account": "Konto",
|
||||
"content_discovery": "Inhalt & Entdeckung",
|
||||
"appearance": "Aussehen",
|
||||
|
|
|
|||
|
|
@ -632,6 +632,7 @@
|
|||
"italian": "Italian",
|
||||
"croatian": "Croatian",
|
||||
"chinese": "Chinese (Simplified)",
|
||||
"hindi": "Hindi",
|
||||
"account": "Account",
|
||||
"content_discovery": "Content & Discovery",
|
||||
"appearance": "Appearance",
|
||||
|
|
|
|||
|
|
@ -632,6 +632,7 @@
|
|||
"italian": "Italiano",
|
||||
"croatian": "Croata",
|
||||
"chinese": "Chino (Simplificado)",
|
||||
"hindi": "Hindi",
|
||||
"account": "Cuenta",
|
||||
"content_discovery": "Contenido y descubrimiento",
|
||||
"appearance": "Apariencia",
|
||||
|
|
|
|||
|
|
@ -632,6 +632,7 @@
|
|||
"italian": "Italien",
|
||||
"croatian": "Croate",
|
||||
"chinese": "Chinois (Simplifié)",
|
||||
"hindi": "Hindi",
|
||||
"account": "Compte",
|
||||
"content_discovery": "Contenu et découverte",
|
||||
"appearance": "Apparence",
|
||||
|
|
|
|||
1366
src/i18n/locales/hi.json
Normal file
1366
src/i18n/locales/hi.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -632,6 +632,7 @@
|
|||
"italian": "Talijanski",
|
||||
"croatian": "Hrvatski",
|
||||
"chinese": "Kineski (Pojednostavljeni)",
|
||||
"hindi": "Hindski",
|
||||
"account": "Račun",
|
||||
"content_discovery": "Sadržaj i otkrivanje",
|
||||
"appearance": "Izgled",
|
||||
|
|
|
|||
|
|
@ -632,6 +632,7 @@
|
|||
"italian": "Italiano",
|
||||
"croatian": "Croato",
|
||||
"chinese": "Cinese (Semplificato)",
|
||||
"hindi": "Hindi",
|
||||
"account": "Account",
|
||||
"content_discovery": "Contenuti e Scoperta",
|
||||
"appearance": "Aspetto",
|
||||
|
|
|
|||
|
|
@ -646,6 +646,7 @@
|
|||
"italian": "Italiano",
|
||||
"croatian": "Croata",
|
||||
"chinese": "Chinês (Simplificado)",
|
||||
"hindi": "Hindi",
|
||||
"account": "Conta",
|
||||
"content_discovery": "Conteúdo e Descoberta",
|
||||
"appearance": "Aparência",
|
||||
|
|
|
|||
|
|
@ -646,6 +646,7 @@
|
|||
"italian": "Italiano",
|
||||
"croatian": "Croata",
|
||||
"chinese": "Chinês (Simplificado)",
|
||||
"hindi": "Hindi",
|
||||
"account": "Conta",
|
||||
"content_discovery": "Conteúdo e Descoberta",
|
||||
"appearance": "Aparência",
|
||||
|
|
|
|||
|
|
@ -632,6 +632,7 @@
|
|||
"italian": "意大利语",
|
||||
"croatian": "克罗地亚语",
|
||||
"chinese": "简体中文",
|
||||
"hindi": "印地语",
|
||||
"account": "账户",
|
||||
"content_discovery": "内容与发现",
|
||||
"appearance": "外观",
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import it from './locales/it.json';
|
|||
import de from './locales/de.json';
|
||||
|
||||
import hr from './locales/hr.json';
|
||||
import hi from './locales/hi.json';
|
||||
import zhCN from './locales/zh-CN.json';
|
||||
|
||||
export const resources = {
|
||||
|
|
@ -21,4 +22,5 @@ export const resources = {
|
|||
de: { translation: de },
|
||||
hr: { translation: hr },
|
||||
'zh-CN': { translation: zhCN },
|
||||
hi: { translation: hi },
|
||||
};
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ const DonorCard: React.FC<DonorCardProps> = ({ donor, currentTheme, isTablet })
|
|||
try {
|
||||
const date = new Date(dateString);
|
||||
if (isNaN(date.getTime())) return dateString;
|
||||
|
||||
|
||||
return date.toLocaleDateString(undefined, {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
|
|
@ -333,7 +333,7 @@ const ContributorsScreen: React.FC = () => {
|
|||
try {
|
||||
const date = new Date(dateString);
|
||||
if (isNaN(date.getTime())) return dateString;
|
||||
|
||||
|
||||
// Use locale-aware formatting
|
||||
return date.toLocaleDateString(undefined, {
|
||||
year: 'numeric',
|
||||
|
|
@ -382,15 +382,17 @@ const ContributorsScreen: React.FC = () => {
|
|||
const sorted = Array.from(map.values()).sort((a, b) => b.total - a.total);
|
||||
|
||||
let lastTotal: number | null = null;
|
||||
let lastRank = 0;
|
||||
let currentRank = 0;
|
||||
|
||||
return sorted.map((entry, index) => {
|
||||
const rank = lastTotal !== null && entry.total === lastTotal ? lastRank : index + 1;
|
||||
return sorted.map((entry) => {
|
||||
if (lastTotal === null || entry.total !== lastTotal) {
|
||||
currentRank += 1;
|
||||
}
|
||||
lastTotal = entry.total;
|
||||
lastRank = rank;
|
||||
|
||||
return {
|
||||
...entry,
|
||||
rank,
|
||||
rank: currentRank,
|
||||
};
|
||||
});
|
||||
}, [donations, getDonationTs]);
|
||||
|
|
@ -803,87 +805,87 @@ const ContributorsScreen: React.FC = () => {
|
|||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{donationsLoading ? (
|
||||
<View style={styles.loadingContainer}>
|
||||
<ActivityIndicator size="large" color={currentTheme.colors.primary} />
|
||||
<Text style={[styles.loadingText, { color: currentTheme.colors.mediumEmphasis }]}>{t('contributors.loading_donors')}</Text>
|
||||
</View>
|
||||
) : donationsError ? (
|
||||
<View style={styles.errorContainer}>
|
||||
<Feather name="alert-circle" size={48} color={currentTheme.colors.mediumEmphasis} />
|
||||
<Text style={[styles.errorText, { color: currentTheme.colors.mediumEmphasis }]}>
|
||||
{donationsError}
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
style={[styles.retryButton, { backgroundColor: currentTheme.colors.primary }]}
|
||||
onPress={() => loadDonations(true)}
|
||||
>
|
||||
<Text style={[styles.retryText, { color: currentTheme.colors.white }]}>{t('common.retry')}</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
) : donations.length === 0 ? (
|
||||
<View style={styles.emptyContainer}>
|
||||
<Feather name="gift" size={48} color={currentTheme.colors.mediumEmphasis} />
|
||||
<Text style={[styles.emptyText, { color: currentTheme.colors.mediumEmphasis }]}>{t('contributors.no_donors')}</Text>
|
||||
</View>
|
||||
{donationsLoading ? (
|
||||
<View style={styles.loadingContainer}>
|
||||
<ActivityIndicator size="large" color={currentTheme.colors.primary} />
|
||||
<Text style={[styles.loadingText, { color: currentTheme.colors.mediumEmphasis }]}>{t('contributors.loading_donors')}</Text>
|
||||
</View>
|
||||
) : donationsError ? (
|
||||
<View style={styles.errorContainer}>
|
||||
<Feather name="alert-circle" size={48} color={currentTheme.colors.mediumEmphasis} />
|
||||
<Text style={[styles.errorText, { color: currentTheme.colors.mediumEmphasis }]}>
|
||||
{donationsError}
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
style={[styles.retryButton, { backgroundColor: currentTheme.colors.primary }]}
|
||||
onPress={() => loadDonations(true)}
|
||||
>
|
||||
<Text style={[styles.retryText, { color: currentTheme.colors.white }]}>{t('common.retry')}</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
) : donations.length === 0 ? (
|
||||
<View style={styles.emptyContainer}>
|
||||
<Feather name="gift" size={48} color={currentTheme.colors.mediumEmphasis} />
|
||||
<Text style={[styles.emptyText, { color: currentTheme.colors.mediumEmphasis }]}>{t('contributors.no_donors')}</Text>
|
||||
</View>
|
||||
) : (
|
||||
donorsTab === 'latest' ? (
|
||||
latestDonations.map((donor, index) => (
|
||||
<DonorCard
|
||||
key={`${donor.name}-${donor.date}-${index}`}
|
||||
donor={donor}
|
||||
currentTheme={currentTheme}
|
||||
isTablet={isTablet}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
donorsTab === 'latest' ? (
|
||||
latestDonations.map((donor, index) => (
|
||||
<DonorCard
|
||||
key={`${donor.name}-${donor.date}-${index}`}
|
||||
donor={donor}
|
||||
currentTheme={currentTheme}
|
||||
isTablet={isTablet}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
leaderboardDonations.map((entry, index) => (
|
||||
<View
|
||||
key={`${entry.name}-${entry.currency}-${index}`}
|
||||
style={[
|
||||
styles.leaderboardCard,
|
||||
{ backgroundColor: currentTheme.colors.elevation1 },
|
||||
isTablet && styles.tabletContributorCard
|
||||
]}
|
||||
>
|
||||
<View style={styles.leaderboardAvatar}>
|
||||
{getRankAnimation(entry.rank) ? (
|
||||
<View style={styles.leaderboardBadge}>
|
||||
<Text style={[styles.leaderboardRankText, { color: currentTheme.colors.white }]}>{entry.rank}</Text>
|
||||
<LottieView
|
||||
source={getRankAnimation(entry.rank)}
|
||||
autoPlay
|
||||
loop={false}
|
||||
style={styles.leaderboardLottie}
|
||||
/>
|
||||
</View>
|
||||
) : (
|
||||
leaderboardDonations.map((entry, index) => (
|
||||
<View
|
||||
key={`${entry.name}-${entry.currency}-${index}`}
|
||||
style={[
|
||||
styles.leaderboardCard,
|
||||
{ backgroundColor: currentTheme.colors.elevation1 },
|
||||
isTablet && styles.tabletContributorCard
|
||||
]}
|
||||
>
|
||||
<View style={styles.leaderboardAvatar}>
|
||||
{getRankAnimation(entry.rank) ? (
|
||||
<View style={styles.leaderboardBadge}>
|
||||
<Text style={[styles.leaderboardRankText, { color: currentTheme.colors.white }]}>{entry.rank}</Text>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.contributorInfo}>
|
||||
<Text style={[
|
||||
styles.username,
|
||||
{ color: currentTheme.colors.highEmphasis },
|
||||
isTablet && styles.tabletUsername
|
||||
]}>
|
||||
{entry.name}
|
||||
</Text>
|
||||
<Text style={[
|
||||
styles.donorAmount,
|
||||
{ color: currentTheme.colors.mediumEmphasis },
|
||||
isTablet && styles.tabletContributions
|
||||
]}>
|
||||
{entry.total.toFixed(2)} {entry.currency} · {entry.count} {entry.count === 1 ? 'donation' : 'donations'}
|
||||
</Text>
|
||||
<Text style={[styles.donorMessage, { color: currentTheme.colors.mediumEmphasis }]}>
|
||||
Rank #{entry.rank} · Last: {formatDonationDate(entry.lastDate)}
|
||||
</Text>
|
||||
</View>
|
||||
<LottieView
|
||||
source={getRankAnimation(entry.rank)}
|
||||
autoPlay
|
||||
loop={false}
|
||||
style={styles.leaderboardLottie}
|
||||
/>
|
||||
</View>
|
||||
) : (
|
||||
<Text style={[styles.leaderboardRankText, { color: currentTheme.colors.white }]}>{entry.rank}</Text>
|
||||
)}
|
||||
</View>
|
||||
))
|
||||
)
|
||||
)}
|
||||
<View style={styles.contributorInfo}>
|
||||
<Text style={[
|
||||
styles.username,
|
||||
{ color: currentTheme.colors.highEmphasis },
|
||||
isTablet && styles.tabletUsername
|
||||
]}>
|
||||
{entry.name}
|
||||
</Text>
|
||||
<Text style={[
|
||||
styles.donorAmount,
|
||||
{ color: currentTheme.colors.mediumEmphasis },
|
||||
isTablet && styles.tabletContributions
|
||||
]}>
|
||||
{entry.total.toFixed(2)} {entry.currency} · {entry.count} {entry.count === 1 ? 'donation' : 'donations'}
|
||||
</Text>
|
||||
<Text style={[styles.donorMessage, { color: currentTheme.colors.mediumEmphasis }]}>
|
||||
Rank #{entry.rank} · Last: {formatDonationDate(entry.lastDate)}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
))
|
||||
)
|
||||
)}
|
||||
</ScrollView>
|
||||
) : activeTab === 'contributors' ? (
|
||||
// Contributors Tab
|
||||
|
|
|
|||
|
|
@ -183,6 +183,15 @@ export const AboutSettingsContent: React.FC<AboutSettingsContentProps> = ({
|
|||
return (
|
||||
<>
|
||||
<SettingsCard title={t('settings.sections.information')} isTablet={isTablet}>
|
||||
{isTablet && (
|
||||
<SettingItem
|
||||
title={t('contributors.title', 'Contributors')}
|
||||
icon="users"
|
||||
onPress={() => navigation.navigate('Contributors')}
|
||||
renderControl={() => <ChevronRight />}
|
||||
isTablet={isTablet}
|
||||
/>
|
||||
)}
|
||||
<SettingItem
|
||||
title={t('settings.items.legal')}
|
||||
icon="file-text"
|
||||
|
|
|
|||
Loading…
Reference in a new issue