Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
230 changes: 230 additions & 0 deletions package/src/i18n/ar.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
{
"+{{count}}_few": "+{{count}}",
"+{{count}}_many": "+{{count}}",
"+{{count}}_one": "+{{count}}",
"+{{count}}_other": "+{{count}}",
"+{{count}}_two": "+{{count}}",
"+{{count}}_zero": "+{{count}}",
"1 Reply": "رد واحد",
"1 Thread Reply": "رد واحد في الموضوع",
"Add a comment": "أضف تعليقاً",
"Add an option": "أضف خياراً",
"Allow access to your Gallery": "اسمح بالوصول إلى المعرض",
"Allow camera access in device settings": "اسمح بالوصول إلى الكاميرا في إعدادات الجهاز",
"Also send to channel": "أرسل أيضاً إلى القناة",
"Anonymous": "مجهول",
"Anonymous voting": "تصويت مجهول",
"Are you sure you want to permanently delete this message?": "هل أنت متأكد أنك تريد حذف هذه الرسالة نهائياً؟",
"Are you sure?": "هل أنت متأكد؟",
"Ask a question": "اطرح سؤالاً",
"Ban User": "منع المستخدم",
"Block User": "حظر المستخدم",
"Cancel": "إلغاء",
"Cannot Flag Message": "تعذر الإبلاغ عن الرسالة",
"Consider how your comment might make others feel and be sure to follow our Community Guidelines": "فكّر في تأثير تعليقك على الآخرين وتأكد من اتباع إرشادات مجتمعنا",
"Copy Message": "نسخ الرسالة",
"Create Poll": "إنشاء تصويت",
"Delete": "حذف",
"Delete Message": "حذف الرسالة",
"Delete for me": "حذف لدي",
"Device camera is used to take photos or videos.": "تُستخدم كاميرا الجهاز لالتقاط الصور أو الفيديو.",
"Device gallery permissions is used to take photos or videos.": "تُستخدم أذونات معرض الجهاز لالتقاط الصور أو الفيديو.",
"Do you want to send a copy of this message to a moderator for further investigation?": "هل تريد إرسال نسخة من هذه الرسالة إلى مشرف لمزيد من المراجعة؟",
"Due since {{ dueSince }}": "مستحق منذ {{ dueSince }}",
"Edit Message": "تعديل الرسالة",
"Edited": "تم التعديل",
"Editing Message": "جارٍ تعديل الرسالة",
"Emoji matching": "مطابقة الإيموجي",
"Empty message...": "رسالة فارغة...",
"End Vote": "إنهاء التصويت",
"Error loading": "خطأ في التحميل",
"Error loading channel list...": "خطأ في تحميل قائمة القنوات...",
"Error loading messages for this channel...": "خطأ في تحميل رسائل هذه القناة...",
"Error marking message unread. Cannot mark unread messages older than the newest 100 channel messages.": "خطأ في وضع علامة غير مقروء. لا يمكن وضع علامة غير مقروء للرسائل الأقدم من أحدث 100 رسالة في القناة.",
"Error while loading, please reload/refresh": "حدث خطأ أثناء التحميل، يرجى إعادة التحميل/التحديث",
"File is too large: {{ size }}, maximum upload size is {{ limit }}": "الملف كبير جدًا: {{ size }}، الحد الأقصى للرفع هو {{ limit }}",
"File type not supported": "نوع الملف غير مدعوم",
"Flag": "إبلاغ",
"Flag Message": "الإبلاغ عن الرسالة",
"Flag action failed either due to a network issue or the message is already flagged": "فشلت عملية الإبلاغ بسبب مشكلة في الشبكة أو لأن الرسالة مبلّغ عنها بالفعل.",
"Generating...": "جارٍ الإنشاء...",
"Hold to start recording.": "اضغط مطولاً لبدء التسجيل.",
"How about sending your first message to a friend?": "ما رأيك في إرسال أول رسالة إلى صديق؟",
"Instant Commands": "الأوامر السريعة",
"Let's start chatting!": "لنبدأ الدردشة!",
"Links are disabled": "الروابط معطلة",
"Loading channels...": "جارٍ تحميل القنوات...",
"Loading messages...": "جارٍ تحميل الرسائل...",
"Loading threads...": "جارٍ تحميل المواضيع...",
"Loading...": "جارٍ التحميل...",
"Location": "الموقع",
"Mark as Unread": "وضع كغير مقروء",
"Maximum number of files reached": "تم الوصول إلى الحد الأقصى لعدد الملفات",
"Message Reactions": "تفاعلات الرسالة",
"Message deleted": "تم حذف الرسالة",
"Message flagged": "تم الإبلاغ عن الرسالة",
"Multiple votes": "تصويتات متعددة",
"Select more than one option": "اختر أكثر من خيار واحد",
"Limit votes per person": "تحديد عدد الأصوات لكل شخص",
"Choose between 2–10 options": "اختر بين 2 و10 خيارات",
"Mute User": "كتم المستخدم",
"No chats here yet…": "لا توجد محادثات هنا بعد…",
"No threads here yet": "لا توجد مواضيع هنا بعد",
"Not supported": "غير مدعوم",
"Nothing yet...": "لا شيء بعد...",
"Ok": "حسناً",
"Only visible to you": "مرئي لك فقط",
"Open Settings": "فتح الإعدادات",
"Option": "خيار",
"Option {{count}}": "الخيار {{count}}",
"Option already exists": "الخيار موجود بالفعل",
"Options": "الخيارات",
"Photo": "صورة",
"Photos and Videos": "الصور ومقاطع الفيديو",
"Pin to Conversation": "تثبيت في المحادثة",
"Pinned by": "مثبّت بواسطة",
"Please allow Audio permissions in settings.": "يرجى السماح بأذونات الصوت في الإعدادات.",
"Please enable access to your photos and videos so you can share them.": "يرجى تفعيل الوصول إلى صورك ومقاطع الفيديو حتى تتمكن من مشاركتها.",
"Please select a channel first": "يرجى اختيار قناة أولاً",
"Poll Comments": "تعليقات التصويت",
"Poll Options": "خيارات التصويت",
"Poll Results": "نتائج التصويت",
"Questions": "الأسئلة",
"Reconnecting...": "جارٍ إعادة الاتصال...",
"Reply": "رد",
"Reply to Message": "الرد على الرسالة",
"Resend": "إعادة الإرسال",
"SEND": "إرسال",
"Search": "بحث",
"Select More Photos": "اختيار المزيد من الصور",
"Select one": "اختر واحداً",
"Select one or more": "اختر واحداً أو أكثر",
"Select up to {{count}}_few": "اختر حتى {{count}}",
"Select up to {{count}}_many": "اختر حتى {{count}}",
"Select up to {{count}}_one": "اختر حتى {{count}}",
"Select up to {{count}}_other": "اختر حتى {{count}}",
"Select up to {{count}}_two": "اختر حتى {{count}}",
"Select up to {{count}}_zero": "اختر حتى {{count}}",
"Send Anyway": "أرسل على أي حال",
"Send a message": "أرسل رسالة",
"Sending links is not allowed in this conversation": "إرسال الروابط غير مسموح في هذه المحادثة",
"Show All": "عرض الكل",
"Slide to Cancel": "اسحب للإلغاء",
"Slow mode ON": "الوضع البطيء قيد التشغيل",
"Slow mode, wait {{seconds}}s...": "وضع بطيء، انتظر {{seconds}}ث...",
"Suggest an option": "اقترح خياراً",
"The message has been reported to a moderator.": "تم الإبلاغ عن الرسالة إلى مشرف.",
"The source message was deleted": "تم حذف الرسالة الأصلية",
"Thinking...": "جارٍ التفكير...",
"This reply was deleted": "تم حذف هذا الرد",
"Thread Reply": "رد في الموضوع",
"Type a number from 2 to 10": "اكتب رقماً من 2 إلى 10",
"Unban User": "إلغاء منع المستخدم",
"Unblock User": "إلغاء حظر المستخدم",
"Unknown User": "مستخدم غير معروف",
"Unmute User": "إلغاء كتم المستخدم",
"Unpin from Conversation": "إلغاء التثبيت من المحادثة",
"Unread Messages": "رسائل غير مقروءة",
"Update your comment": "حدّث تعليقك",
"Video": "فيديو",
"View Results": "عرض النتائج",
"View {{count}} comments_few": "عرض {{count}} تعليقات",
"View {{count}} comments_many": "عرض {{count}} تعليقات",
"View {{count}} comments_one": "عرض {{count}} تعليق",
"View {{count}} comments_other": "عرض {{count}} تعليقات",
"View {{count}} comments_two": "عرض تعليقين",
"View {{count}} comments_zero": "عرض التعليقات",
"Voice message": "رسالة صوتية",
"You": "أنت",
"You can't send messages in this channel": "لا يمكنك إرسال رسائل في هذه القناة",
"duration/Location end at": "{{ milliseconds | durationFormatter(withSuffix: false) }}",
"duration/Message reminder": "{{ milliseconds | durationFormatter(withSuffix: true) }}",
"duration/Remind Me": "{{ milliseconds | durationFormatter(withSuffix: true) }}",
"replied to": "رد على",
"timestamp/ChannelPreviewStatus": "{{ timestamp | timestampFormatter(calendar: true; calendarFormats: {\"lastDay\":\"[أمس]\", \"lastWeek\":\"dddd\", \"nextDay\":\"[غدًا]\", \"nextWeek\":\"dddd [في] LT\", \"sameDay\":\"LT\", \"sameElse\":\"L\"}) }}",
"timestamp/ImageGalleryHeader": "{{ timestamp | timestampFormatter(calendar: true) }}",
"timestamp/InlineDateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}",
"timestamp/MessageEditedTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}",
"timestamp/MessageSystem": "{{ timestamp | timestampFormatter(calendar: true) }}",
"timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(format: LT) }}",
"timestamp/PollVote": "{{ timestamp | relativeCompactDateFormatter }}",
"timestamp/ReminderNotification": "{{ timestamp | timestampFormatter(calendar: true) }}",
"timestamp/StickyHeader": "{{ timestamp | timestampFormatter(calendar: true) }}",
"timestamp/ThreadListItem": "{{ timestamp | timestampFormatter(calendar: true; calendarFormats: {\"lastDay\":\"[أمس]\", \"lastWeek\":\"dddd\", \"nextDay\":\"[غدًا]\", \"nextWeek\":\"dddd [في] LT\", \"sameDay\":\"LT\", \"sameElse\":\"L\"}) }}",
"{{ firstUser }} and {{ nonSelfUserLength }} more are typing": "{{ firstUser }} و{{ nonSelfUserLength }} آخرون يكتبون",
"{{ index }} of {{ photoLength }}": "{{ index }} من {{ photoLength }}",
"{{ replyCount }} Replies": "{{ replyCount }} ردود",
"{{ user }} is typing": "{{ user }} يكتب",
"You voted: {{ option }}": "لقد صوّتَّ: {{ option }}",
"{{ firstUser }} and {{ secondUser }} are typing": "{{ firstUser }} و{{ secondUser }} يكتبان",
"{{ numberOfUsers }} people are typing": "{{ numberOfUsers }} أشخاص يكتبون",
"Typing": "يكتب",
"No messages yet": "لا توجد رسائل بعد",
"Message failed to send": "فشل إرسال الرسالة",
"and {{ count }} others": "و{{ count }} آخرون",
"{{ user }} voted: {{ option }}": "{{ user }} صوّت: {{ option }}",
"{{count}} votes_few": "{{count}} أصوات",
"{{count}} votes_many": "{{count}} أصوات",
"{{count}} votes_one": "{{count}} صوت",
"{{count}} votes_other": "{{count}} أصوات",
"{{count}} votes_two": "صوتان",
"{{count}} votes_zero": "لا أصوات",
"🏙 Attachment...": "🏙 مرفق...",
"You have not granted access to the photo library.": "لم تمنح إذن الوصول إلى مكتبة الصور.",
"Change in Settings": "التغيير في الإعدادات",
"Create a poll and let everyone vote": "أنشئ تصويتاً ودع الجميع يصوّت",
"Open Camera": "فتح الكاميرا",
"Pick a document to share it with everyone": "اختر مستندًا لمشاركته مع الجميع",
"Pick document": "اختر مستنداً",
"Take a video and share": "التقط فيديو وشاركه",
"You have not granted access to your camera": "لم تمنح إذن الوصول إلى الكاميرا",
"{{count}} Reactions_few": "{{count}} تفاعلات",
"{{count}} Reactions_many": "{{count}} تفاعلات",
"{{count}} Reactions_one": "{{count}} تفاعل",
"{{count}} Reactions_other": "{{count}} تفاعلات",
"{{count}} Reactions_two": "تفاعلان",
"{{count}} Reactions_zero": "لا تفاعلات",
"Tap to remove": "اضغط للإزالة",
"Draft": "مسودة",
"Reminder set": "تم ضبط التذكير",
"Also sent in channel": "تم الإرسال أيضًا في القناة",
"Replied to a thread": "تم الرد في موضوع",
"View": "عرض",
"Reminder overdue": "انتهى وقت التذكير",
"Poll has ended": "انتهى التصويت",
"Reply to a message to start a thread": "قم بالرد على رسالة لبدء موضوع",
"Couldn't load new threads. Tap to retry": "تعذر تحميل المواضيع الجديدة. اضغط لإعادة المحاولة",
"{{count}} new threads": "{{count}} مواضيع جديدة",
"No conversations yet": "لا توجد محادثات بعد",
"Are you sure you want to delete this group? This can't be undone.": "هل أنت متأكد أنك تريد حذف هذه المجموعة؟ لا يمكن التراجع عن هذا.",
"Are you sure you want to delete this chat? This can't be undone.": "هل أنت متأكد أنك تريد حذف هذه الدردشة؟ لا يمكن التراجع عن هذا.",
"Delete chat": "حذف الدردشة",
"Delete group": "حذف المجموعة",
"Archive Chat": "أرشفة الدردشة",
"Archive Group": "أرشفة المجموعة",
"Delete Chat": "حذف الدردشة",
"Delete Group": "حذف المجموعة",
"Leave Chat": "مغادرة الدردشة",
"Leave Group": "مغادرة المجموعة",
"Mute Group": "كتم المجموعة",
"Offline": "غير متصل",
"Online": "متصل",
"Unarchive Chat": "إلغاء أرشفة الدردشة",
"Unarchive Group": "إلغاء أرشفة المجموعة",
"Unmute Group": "إلغاء كتم المجموعة",
"{{memberCount}} members, {{onlineCount}} online_few": "{{memberCount}} أعضاء، {{onlineCount}} متصل",
"{{memberCount}} members, {{onlineCount}} online_many": "{{memberCount}} أعضاء، {{onlineCount}} متصل",
"{{memberCount}} members, {{onlineCount}} online_one": "{{memberCount}} عضو، {{onlineCount}} متصل",
"{{memberCount}} members, {{onlineCount}} online_other": "{{memberCount}} أعضاء، {{onlineCount}} متصل",
"{{memberCount}} members, {{onlineCount}} online_two": "عضوان، {{onlineCount}} متصل",
"{{memberCount}} members, {{onlineCount}} online_zero": "لا أعضاء",
"{{count}} unread": "{{count}} غير مقروء",
"{{count}} new messages": "{{count}} رسائل جديدة",
"Unsupported Attachment": "مرفق غير مدعوم",
"+{{count}} More Options_few": "+{{count}} خيارات إضافية",
"+{{count}} More Options_many": "+{{count}} خيارات إضافية",
"+{{count}} More Options_one": "+{{count}} خيار إضافي",
"+{{count}} More Options_other": "+{{count}} خيارات إضافية",
"+{{count}} More Options_two": "+{{count}} خيارات إضافية",
"+{{count}} More Options_zero": "+{{count}} خيارات إضافية"
}
65 changes: 65 additions & 0 deletions package/src/utils/__tests__/Streami18n.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { default as Dayjs } from 'dayjs';
import 'dayjs/locale/ar';
import 'dayjs/locale/nl';
import localeData from 'dayjs/plugin/localeData';
import moment from 'moment-timezone';

import arTranslations from '../../i18n/ar.json';
import frTranslations from '../../i18n/fr.json';
import nlTranslations from '../../i18n/nl.json';
import { Streami18n } from '../i18n/Streami18n';
Expand Down Expand Up @@ -43,6 +45,69 @@ describe('Streami18n instance - default', () => {
});
});

describe('Streami18n instance - Arabic language (ar)', () => {
describe('datetime translations enabled', () => {
const streami18nOptions = { language: 'ar' };
const streami18n = new Streami18n(streami18nOptions);
it('should provide arabic translator', async () => {
const { t: _t } = await streami18n.getTranslators();
for (const key in arTranslations) {
const value = arTranslations[key];
const hasTemplateInKey = key.indexOf('{{') > -1 && key.indexOf('}}') > -1;
const hasTemplateInValue =
typeof value === 'string' && value.indexOf('{{') > -1 && value.indexOf('}}') > -1;
if (
hasTemplateInKey ||
hasTemplateInValue ||
key.indexOf('duration/') > -1 ||
key.indexOf('timestamp/') > -1
) {
continue;
}
expect(_t(key)).toBe(arTranslations[key]);
}
});
it('should provide dayjs with `ar` locale', async () => {
const { tDateTimeParser } = await streami18n.getTranslators();
expect(tDateTimeParser() instanceof Dayjs).toBe(true);
expect(tDateTimeParser().locale()).toBe('ar');
});
});

describe('datetime translations disabled', () => {
const streami18nOptions = {
disableDateTimeTranslations: true,
language: 'ar',
};
const streami18n = new Streami18n(streami18nOptions);

it('should provide arabic translator', async () => {
const { t: _t } = await streami18n.getTranslators();
for (const key in arTranslations) {
const value = arTranslations[key];
const hasTemplateInKey = key.indexOf('{{') > -1 && key.indexOf('}}') > -1;
const hasTemplateInValue =
typeof value === 'string' && value.indexOf('{{') > -1 && value.indexOf('}}') > -1;
if (
hasTemplateInKey ||
hasTemplateInValue ||
key.indexOf('duration/') > -1 ||
key.indexOf('timestamp/') > -1
) {
continue;
}
expect(_t(key)).toBe(arTranslations[key]);
}
});

it('should provide dayjs with default `en` locale when datetime translations disabled', async () => {
const { tDateTimeParser } = await streami18n.getTranslators();
expect(tDateTimeParser() instanceof Dayjs).toBe(true);
expect(tDateTimeParser().locale()).toBe('en');
});
});
});

describe('Streami18n instance - with built-in language', () => {
describe('datetime translations enabled', () => {
const streami18nOptions = { language: 'nl' };
Expand Down
6 changes: 6 additions & 0 deletions package/src/utils/i18n/Streami18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { predefinedFormatters } from './predefinedFormatters';
import { CustomFormatters, PredefinedFormatters } from './types';

import type { TDateTimeParser } from '../../contexts/translationContext/types';
import arTranslations from '../../i18n/ar.json';
import enTranslations from '../../i18n/en.json';
import esTranslations from '../../i18n/es.json';
import frTranslations from '../../i18n/fr.json';
Expand All @@ -28,6 +29,7 @@ import ptBRTranslations from '../../i18n/pt-br.json';
import ruTranslations from '../../i18n/ru.json';
import trTranslations from '../../i18n/tr.json';

import 'dayjs/locale/ar';
import 'dayjs/locale/es';
import 'dayjs/locale/fr';
import 'dayjs/locale/he';
Expand Down Expand Up @@ -65,6 +67,9 @@ Dayjs.updateLocale('en', {
},
});

Dayjs.updateLocale('ar', {
calendar: calendarFormats.ar,
});
Dayjs.updateLocale('es', {
calendar: calendarFormats.es,
});
Expand Down Expand Up @@ -393,6 +398,7 @@ export class Streami18n {
[key: string]: Partial<typeof enTranslations>;
};
} = {
ar: { [defaultNS]: arTranslations },
en: { [defaultNS]: enTranslations },
es: { [defaultNS]: esTranslations },
fr: { [defaultNS]: frTranslations },
Expand Down
Loading