Support new plural keys format.

All the old plural phrases were changed to work with the new format.
This commit is contained in:
John Preston 2017-06-02 14:46:02 +03:00
parent b6046d829f
commit 85e6f55536
27 changed files with 593 additions and 298 deletions

View File

@ -88,7 +88,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_continue" = "Continue";
"lng_close" = "Close";
"lng_connecting" = "Connecting...";
"lng_reconnecting" = "Reconnect {count:now|in # s|in # s}...";
"lng_reconnecting#one" = "Reconnect in {count} s...";
"lng_reconnecting#other" = "Reconnect in {count} s...";
"lng_reconnecting_try_now" = "Try now";
"lng_status_service_notifications" = "service notifications";
@ -102,8 +103,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_status_last_month" = "last seen within a month";
"lng_status_invisible" = "invisible";
"lng_status_lastseen_now" = "last seen just now";
"lng_status_lastseen_minutes" = "last seen {count:_not_used_|# minute|# minutes} ago";
"lng_status_lastseen_hours" = "last seen {count:_not_used_|# hour|# hours} ago";
"lng_status_lastseen_minutes#one" = "last seen {count} minute ago";
"lng_status_lastseen_minutes#other" = "last seen {count} minutes ago";
"lng_status_lastseen_hours#one" = "last seen {count} hour ago";
"lng_status_lastseen_hours#other" = "last seen {count} hours ago";
"lng_status_lastseen_today" = "last seen today at {time}";
"lng_status_lastseen_yesterday" = "last seen yesterday at {time}";
"lng_status_lastseen_date" = "last seen {date}";
@ -112,14 +115,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_status_connecting" = "connecting...";
"lng_chat_status_unaccessible" = "group is inaccessible";
"lng_chat_status_members" = "{count:no members|# member|# members}";
"lng_chat_status_members_online" = "{count:_not_used_|# member|# members}, {count_online:_not_used_|# online|# online}";
"lng_chat_status_no_members" = "no members";
"lng_chat_status_members#one" = "{count} member";
"lng_chat_status_members#other" = "{count} members";
"lng_chat_status_online#one" = "{count} online";
"lng_chat_status_online#other" = "{count} online";
"lng_chat_status_members_online" = "{members_count}, {online_count}";
"lng_channel_status" = "channel";
"lng_group_status" = "group";
"lng_channel_members_link" = "{count:_not_used_|# member|# members}";
"lng_channel_admins_link" = "{count:_not_used_|# administrator|# administrators}";
"lng_channel_members_link#one" = "{count} member";
"lng_channel_members_link#other" = "{count} members";
"lng_channel_admins_link#one" = "{count} administrator";
"lng_channel_admins_link#other" = "{count} administrators";
"lng_server_error" = "Internal server error.";
"lng_flood_error" = "Too many tries. Please try again later.";
@ -128,7 +137,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_join_channel_error" = "Sorry, you have joined too many channels and supergroups. Please leave some before joining.";
"lng_error_phone_flood" = "Sorry, you have deleted and re-created your account too many times recently. Please wait for a few days before signing up again.";
"lng_error_start_minimized_passcoded" = "You have set a local passcode, so the app can't be launched minimized. App will ask you to enter the passcode before it can start working.";
"lng_error_pinned_max" = "Sorry, you can pin no more than {count:_not_used_|# chat|# chats} to the top.";
"lng_error_pinned_max#one" = "Sorry, you can pin no more than {count} chat to the top.";
"lng_error_pinned_max#other" = "Sorry, you can pin no more than {count} chats to the top.";
"lng_error_public_groups_denied" = "Unfortunately, you were banned from participating in public groups.\n{more_info}";
"lng_edit_deleted" = "This message was deleted";
@ -198,9 +208,14 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_signin_sure_reset" = "Warning!\n\nYou will lose all your chats and messages, along with any media and files you shared!\n\nDo you want to reset your account?";
"lng_signin_reset" = "Reset";
"lng_signin_reset_wait" = "Since the account {phone_number} is active and protected by a password, we will delete it in 1 week for security purposes. You can cancel this process at any time.\n\nYoull be able to reset your account in:\n{when}";
"lng_signin_reset_in_days" = "{count_days:0 days|# day|# days} {count_hours:0 hours|# hour|# hours} {count_minutes:0 minutes|# minute|# minutes}";
"lng_signin_reset_in_hours" = "{count_hours:0 hours|# hour|# hours} {count_minutes:0 minutes|# minute|# minutes}";
"lng_signin_reset_in_minutes" = "{count_minutes:0 minutes|# minute|# minutes}";
"lng_signin_reset_days#one" = "{count} day";
"lng_signin_reset_days#other" = "{count} days";
"lng_signin_reset_hours#one" = "{count} hour";
"lng_signin_reset_hours#other" = "{count} hours";
"lng_signin_reset_minutes#one" = "{count} minute";
"lng_signin_reset_minutes#other" = "{count} minutes";
"lng_signin_reset_in_days" = "{days_count} {hours_count} {minutes_count}";
"lng_signin_reset_in_hours" = "{hours_count} {minutes_count}";
"lng_signin_reset_cancelled" = "Your recent attempts to reset this account have been cancelled by its active user. Please try again in 7 days.";
"lng_signup_title" = "Your Info";
@ -303,7 +318,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_backgrounds_header" = "Choose your new chat background";
"lng_theme_sure_keep" = "Keep this color theme?";
"lng_theme_reverting" = "Reverting to the old color theme in {count:_not_used_|# second|# seconds}.";
"lng_theme_reverting#one" = "Reverting to the old color theme in {count} second.";
"lng_theme_reverting#other" = "Reverting to the old color theme in {count} seconds.";
"lng_theme_keep_changes" = "Keep changes";
"lng_theme_revert" = "Revert";
@ -329,8 +345,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_local_storage_title" = "Local storage";
"lng_settings_no_data_cached" = "No cached data found!";
"lng_settings_images_cached" = "{count:_not_used_|# image|# images}, {size}";
"lng_settings_audios_cached" = "{count:_not_used_|# voice message|# voice messages}, {size}";
"lng_settings_images_cached#one" = "{count} image, {size}";
"lng_settings_images_cached#other" = "{count} images, {size}";
"lng_settings_audios_cached#one" = "{count} voice message, {size}";
"lng_settings_audios_cached#other" = "{count} voice messages, {size}";
"lng_local_storage_clear" = "Clear all";
"lng_local_storage_clearing" = "Clearing...";
"lng_local_storage_cleared" = "Cleared!";
@ -348,8 +366,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_passcode_autolock" = "Auto-Lock";
"lng_passcode_autolock_away" = "Auto-Lock if away for:";
"lng_passcode_autolock_inactive" = "Auto-Lock if inactive for:";
"lng_passcode_autolock_minutes" = "{count:_not_used_|# minute|# minutes}";
"lng_passcode_autolock_hours" = "{count:_not_used_|# hour|# hours}";
"lng_passcode_autolock_minutes#one" = "{count} minute";
"lng_passcode_autolock_minutes#other" = "{count} minutes";
"lng_passcode_autolock_hours#one" = "{count} hour";
"lng_passcode_autolock_hours#other" = "{count} hours";
"lng_passcode_enter_old" = "Enter current passcode";
"lng_passcode_enter_first" = "Enter a passcode";
"lng_passcode_enter_new" = "Enter new passcode";
@ -455,32 +475,46 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_edit_privacy_lastseen_title" = "Last seen privacy";
"lng_edit_privacy_lastseen_description" = "You can choose who can see your last seen time:";
"lng_edit_privacy_lastseen_warning" = "Important: you won't be able to see Last Seen times for people with whom you don't share your Last Seen time. Approximate last seen will be shown instead (recently, within a week, within a month).";
"lng_edit_privacy_lastseen_always" = "Always share with{count:| # user| # users}";
"lng_edit_privacy_lastseen_never" = "Never share with{count:| # user| # users}";
"lng_edit_privacy_lastseen_always_empty" = "Always share with";
"lng_edit_privacy_lastseen_always#one" = "Always share with {count} user";
"lng_edit_privacy_lastseen_always#other" = "Always share with {count} users";
"lng_edit_privacy_lastseen_never_empty" = "Never share with";
"lng_edit_privacy_lastseen_never#one" = "Never share with {count} user";
"lng_edit_privacy_lastseen_never#other" = "Never share with {count} users";
"lng_edit_privacy_lastseen_exceptions" = "These settings will override the values above.";
"lng_edit_privacy_lastseen_always_title" = "Always share with";
"lng_edit_privacy_lastseen_never_title" = "Never share with";
"lng_edit_privacy_groups_title" = "Group invite settings";
"lng_edit_privacy_groups_description" = "You can choose who can add you to groups and channels with granular precision:";
"lng_edit_privacy_groups_always" = "Always allow{count:| # user| # users}";
"lng_edit_privacy_groups_never" = "Never allow{count:| # user| # users}";
"lng_edit_privacy_groups_always_empty" = "Always allow";
"lng_edit_privacy_groups_always#one" = "Always allow {count} user";
"lng_edit_privacy_groups_always#other" = "Always allow {count} users";
"lng_edit_privacy_groups_never_empty" = "Never allow";
"lng_edit_privacy_groups_never#one" = "Never allow {count} user";
"lng_edit_privacy_groups_never#other" = "Never allow {count} users";
"lng_edit_privacy_groups_exceptions" = "These users will or will not be able to add you to groups and channels regardless of the settings above.";
"lng_edit_privacy_groups_always_title" = "Always allow";
"lng_edit_privacy_groups_never_title" = "Never allow";
"lng_edit_privacy_calls_title" = "Phone calls privacy";
"lng_edit_privacy_calls_description" = "You can restrict who can call you:";
"lng_edit_privacy_calls_always" = "Always allow{count:| # user| # users}";
"lng_edit_privacy_calls_never" = "Never allow{count:| # user| # users}";
"lng_edit_privacy_calls_always_empty" = "Always allow";
"lng_edit_privacy_calls_always#one" = "Always allow {count} user";
"lng_edit_privacy_calls_always#other" = "Always allow {count} users";
"lng_edit_privacy_calls_never_empty" = "Never allow";
"lng_edit_privacy_calls_never#one" = "Never allow {count} user";
"lng_edit_privacy_calls_never#other" = "Never allow {count} users";
"lng_edit_privacy_calls_exceptions" = "These users will or will not be able to call you regardless of the settings above.";
"lng_edit_privacy_calls_always_title" = "Always allow";
"lng_edit_privacy_calls_never_title" = "Never allow";
"lng_self_destruct_title" = "Account self-destruction";
"lng_self_destruct_description" = "If you don't come online at least once within this period, your account will be deleted along with all groups, messages and contacts.";
"lng_self_destruct_months" = "{count:_not_used_|# month|# months}";
"lng_self_destruct_years" = "{count:_not_used_|# year|# years}";
"lng_self_destruct_months#one" = "{count} month";
"lng_self_destruct_months#other" = "{count} months";
"lng_self_destruct_years#one" = "{count} year";
"lng_self_destruct_years#other" = "{count} years";
"lng_change_phone_title" = "Change phone number";
"lng_change_phone_description" = "You can change your Telegram number\nhere. Your account and all your cloud data\n— messages, media, contacts, etc. will be\nmoved to the new number.\n\n[b]Important[/b]: all your Telegram contacts will\nget your [b]new number[/b] added to their address\nbook, provided they had your old number and\nyou haven't blocked them in Telegram.";
@ -508,7 +542,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_profile_edit_public_link" = "Edit public link";
"lng_profile_manage_admins" = "Manage administrators";
"lng_profile_manage_blocklist" = "Manage blocked users";
"lng_profile_common_groups" = "{count:_not_used_|# group|# groups} in common";
"lng_profile_common_groups#one" = "{count} group in common";
"lng_profile_common_groups#other" = "{count} groups in common";
"lng_profile_common_groups_section" = "Groups in common";
"lng_profile_participants_section" = "Members";
"lng_profile_info_section" = "Info";
@ -548,17 +583,23 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_profile_loading" = "Loading...";
"lng_profile_shared_media" = "Shared media";
"lng_profile_no_media" = "No media in this conversation.";
"lng_profile_photos" = "{count:_not_used_|# photo|# photos}";
"lng_profile_photos#one" = "{count} photo";
"lng_profile_photos#other" = "{count} photos";
"lng_profile_photos_header" = "Photos";
"lng_profile_videos" = "{count:_not_used_|# video|# videos}";
"lng_profile_videos#one" = "{count} video";
"lng_profile_videos#other" = "{count} videos";
"lng_profile_videos_header" = "Videos";
"lng_profile_songs" = "{count:_not_used_|# audio file|# audio files}";
"lng_profile_songs#one" = "{count} audio file";
"lng_profile_songs#other" = "{count} audio files";
"lng_profile_songs_header" = "Audio files";
"lng_profile_files" = "{count:_not_used_|# file|# files}";
"lng_profile_files#one" = "{count} file";
"lng_profile_files#other" = "{count} files";
"lng_profile_files_header" = "Files";
"lng_profile_audios" = "{count:_not_used_|# voice message|# voice messages}";
"lng_profile_audios#one" = "{count} voice message";
"lng_profile_audios#other" = "{count} voice messages";
"lng_profile_audios_header" = "Voice messages";
"lng_profile_shared_links" = "{count:_not_used_|# shared link|# shared links}";
"lng_profile_shared_links#one" = "{count} shared link";
"lng_profile_shared_links#other" = "{count} shared links";
"lng_profile_shared_links_header" = "Shared links";
"lng_profile_copy_phone" = "Copy Phone Number";
"lng_profile_copy_fullname" = "Copy Name";
@ -581,7 +622,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_channel_add_admins" = "New administrator";
"lng_channel_add_members" = "Add members";
"lng_channel_members" = "Members";
"lng_channel_only_last_shown" = "Only the last {count:_not_used_|# member is|# members are} shown here";
"lng_channel_only_last_shown#one" = "Only the last {count} member is shown here";
"lng_channel_only_last_shown#other" = "Only the last {count} members are shown here";
"lng_channel_admins" = "Administrators";
"lng_channel_add_admin" = "Add Administrator";
"lng_channel_admin_sure" = "Add {user} to administrators?";
@ -595,7 +637,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_participant_filter" = "Search";
"lng_participant_invite" = "Invite";
"lng_participant_invite_sorry" = "Sorry, you can only add the first {count:_not_used|# member|# members} to a channel personally.\n\nFrom now on, people will need to join via your invite link.";
"lng_participant_invite_sorry#one" = "Sorry, you can only add the first {count} member to a channel personally.\n\nFrom now on, people will need to join via your invite link.";
"lng_participant_invite_sorry#other" = "Sorry, you can only add the first {count} members to a channel personally.\n\nFrom now on, people will need to join via your invite link.";
"lng_create_group_back" = "Back";
"lng_create_group_next" = "Next";
"lng_create_group_create" = "Create";
@ -637,8 +680,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_message_empty" = "Empty Message";
"lng_message_unsupported" = "This message is not supported by your version of Telegram Desktop. Please update to the last version in Settings or install it from {link}";
"lng_duration_seconds" = "{count:_not_used_|# second|# seconds}";
"lng_duration_minutes_seconds" = "{count_minutes:# min|# min|# min} {count_seconds:# sec|# sec|# sec}";
"lng_duration_seconds#one" = "{count} second";
"lng_duration_seconds#other" = "{count} seconds";
"lng_duration_minsec_minutes#one" = "{count} min";
"lng_duration_minsec_minutes#other" = "{count} min";
"lng_duration_minsec_seconds#one" = "{count} sec";
"lng_duration_minsec_seconds#other" = "{count} sec";
"lng_duration_minutes_seconds" = "{minutes_count} {seconds_count}";
"lng_action_add_user" = "{from} added {user}";
"lng_action_add_users_many" = "{from} added {users}";
@ -676,18 +724,24 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_action_pinned_media_sticker" = "a sticker";
"lng_action_pinned_media_emoji_sticker" = "a {emoji} sticker";
"lng_action_pinned_media_game" = "the game «{game}»";
"lng_action_game_score" = "{from} scored {count:#|#|#} in {game}";
"lng_action_game_you_scored" = "You scored {count:#|#|#} in {game}";
"lng_action_game_score_no_game" = "{from} scored {count:#|#|#}";
"lng_action_game_you_scored_no_game" = "You scored {count:#|#|#}";
"lng_action_game_score#one" = "{from} scored {count} in {game}";
"lng_action_game_score#other" = "{from} scored {count} in {game}";
"lng_action_game_you_scored#one" = "You scored {count} in {game}";
"lng_action_game_you_scored#other" = "You scored {count} in {game}";
"lng_action_game_score_no_game#one" = "{from} scored {count}";
"lng_action_game_score_no_game#other" = "{from} scored {count}";
"lng_action_game_you_scored_no_game#one" = "You scored {count}";
"lng_action_game_you_scored_no_game#other" = "You scored {count}";
"lng_action_payment_done" = "You have just successfully transferred {amount} to {user}";
"lng_action_payment_done_for" = "You have just successfully transferred {amount} to {user} for {invoice}";
"lng_profile_migrate_reached" = "{count:_not_used_|# member|# members} limit reached";
"lng_profile_migrate_reached#one" = "{count} member limit reached";
"lng_profile_migrate_reached#other" = "{count} members limit reached";
"lng_profile_migrate_body" = "To get over this limit, you can upgrade your group to a supergroup.";
"lng_profile_migrate_learn_more" = "Learn more »";
"lng_profile_migrate_about" = "If you'd like to go over this limit, you can upgrade your group to a supergroup. In supergroups:";
"lng_profile_migrate_feature1" = "— The members limit is {count:_not_used_|# user|# users}";
"lng_profile_migrate_feature1#one" = "— The members limit is {count} user";
"lng_profile_migrate_feature1#other" = "— The members limit is {count} users";
"lng_profile_migrate_feature2" = "— New members see the entire chat history";
"lng_profile_migrate_feature3" = "— Admins delete messages for everyone";
"lng_profile_migrate_feature4" = "— Notifications are muted by default";
@ -702,7 +756,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_profile_convert_feature4" = "— Creator can set a public link for the group";
"lng_profile_convert_warning" = "{bold_start}Note:{bold_end} This action can not be undone";
"lng_profile_convert_confirm" = "Convert";
"lng_profile_add_more_after_upgrade" = "You will be able to add up to {count:_not_used_|# member|# members} after you upgrade your group to a supergroup.";
"lng_profile_add_more_after_upgrade#one" = "You will be able to add up to {count} member after you upgrade your group to a supergroup.";
"lng_profile_add_more_after_upgrade#other" = "You will be able to add up to {count} members after you upgrade your group to a supergroup.";
"lng_channel_not_accessible" = "Sorry, this channel is not accessible.";
"lng_group_not_accessible" = "Sorry, this group is not accessible.";
@ -717,7 +772,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_group_invite_want_join_channel" = "Do you want to join the channel «{title}»?";
"lng_group_invite_join" = "Join";
"lng_group_invite_members" = "{count:_not_used_|# member|# members}, among them:";
"lng_group_invite_members#one" = "{count} member, among them:";
"lng_group_invite_members#other" = "{count} members, among them:";
"lng_group_invite_link" = "Invite link:";
"lng_group_invite_create" = "Create an invite link";
@ -810,7 +866,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_stickers_you_have" = "Manage and reorder sticker packs";
"lng_stickers_featured" = "Trending Stickers";
"lng_stickers_return" = "Undo";
"lng_stickers_count" = "{count:Loading...|# sticker|# stickers}";
"lng_stickers_count#one" = "{count} sticker";
"lng_stickers_count#other" = "{count} stickers";
"lng_stickers_masks_pack" = "This is a pack of mask stickers. You can use them in the photo editor on our mobile apps.";
"lng_in_dlg_photo" = "Photo";
@ -885,11 +942,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_typing" = "typing";
"lng_user_typing" = "{user} is typing";
"lng_users_typing" = "{user} and {second_user} are typing";
"lng_many_typing" = "{count:_not_used_|# is|# are} typing";
"lng_many_typing#one" = "{count} is typing";
"lng_many_typing#other" = "{count} are typing";
"lng_playing_game" = "playing a game";
"lng_user_playing_game" = "{user} is playing a game";
"lng_users_playing_game" = "{user} and {second_user} are playing a game";
"lng_many_playing_game" = "{count:_not_used_|# is|# are} playing a game";
"lng_many_playing_game#one" = "{count} is playing a game";
"lng_many_playing_game#other" = "{count} are playing a game";
"lng_send_action_record_video" = "recording a video";
"lng_user_action_record_video" = "{user} is recording a video";
"lng_send_action_upload_video" = "sending a video";
@ -910,7 +969,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_user_action_geo_location" = "{user} is picking a location";
"lng_send_action_choose_contact" = "choosing a contact";
"lng_user_action_choose_contact" = "{user} is choosing a contact";
"lng_unread_bar" = "{count:_not_used_|# unread message|# unread messages}";
"lng_unread_bar#one" = "{count} unread message";
"lng_unread_bar#other" = "{count} unread messages";
"lng_maps_point" = "Location";
"lng_save_photo" = "Save image";
@ -977,15 +1037,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_really_send_image" = "Do you want to send this image?";
"lng_really_send_file" = "Do you want to send this file?";
"lng_really_share_contact" = "Do you want to share this contact?";
"lng_send_images_compress" = "Compress {count:_not_used_|image|images}";
"lng_send_images_compress#one" = "Compress image";
"lng_send_images_compress#other" = "Compress images";
"lng_send_image_non_local" = "Could not send a non local file: {name}";
"lng_send_image_empty" = "Could not send an empty file: {name}";
"lng_send_image_too_large" = "Could not send a file, because it is larger than 1500 MB: {name}";
"lng_send_folder" = "Could not send «{name}» because it is a directory :(";
"lng_send_images_selected" = "{count:_not_used_|# image|# images} selected";
"lng_send_photos" = "Send {count:_not_used_|# photo|# photos}";
"lng_send_files_selected" = "{count:_not_used_|# file|# files} selected";
"lng_send_files" = "Send {count:_not_used_|# file|# files}";
"lng_send_images_selected#one" = "{count} image selected";
"lng_send_images_selected#other" = "{count} images selected";
"lng_send_photos#one" = "Send {count} photo";
"lng_send_photos#other" = "Send {count} photos";
"lng_send_files_selected#one" = "{count} file selected";
"lng_send_files_selected#other" = "{count} files selected";
"lng_send_files#one" = "Send {count} file";
"lng_send_files#other" = "Send {count} files";
"lng_forward_choose" = "Choose recipient...";
"lng_forward_cant" = "Sorry, no way to forward here :(";
@ -994,8 +1059,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_forward_send_file_confirm" = "Send «{name}» to {recipient}?";
"lng_forward_send_files_confirm" = "Send selected files to {recipient}?";
"lng_forward_send" = "Send";
"lng_forward_messages" = "{count:_not_used_|Forwarded message|# forwarded messages}";
"lng_forwarding_from" = "{user} and {count:_not_used_|# other|# others}";
"lng_forward_messages#one" = "{count} forwarded message";
"lng_forward_messages#other" = "{count} forwarded messages";
"lng_forwarding_from#one" = "{user} and {count} other";
"lng_forwarding_from#other" = "{user} and {count} others";
"lng_forwarding_from_two" = "{user} and {second_user}";
"lng_inline_switch_choose" = "Choose conversation...";
"lng_inline_switch_cant" = "Sorry, no way to write here :(";
@ -1041,15 +1108,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_selected_clear" = "Cancel";
"lng_selected_delete" = "Delete";
"lng_selected_forward" = "Forward";
"lng_selected_count" = "{count:_not_used_|# message|# messages}";
"lng_selected_count#one" = "{count} message";
"lng_selected_count#other" = "{count} messages";
"lng_selected_cancel_sure_this" = "Cancel uploading?";
"lng_selected_upload_stop" = "Stop";
"lng_selected_delete_sure_this" = "Do you want to delete this message?";
"lng_selected_delete_sure" = "Do you want to delete {count:_not_used_|# message|# messages}?";
"lng_selected_delete_sure#one" = "Do you want to delete {count} message?";
"lng_selected_delete_sure#other" = "Do you want to delete {count} messages?";
"lng_delete_photo_sure" = "Do you want to delete this photo?";
"lng_delete_for_everyone_hint" = "This will delete {count:_not_used_|it|them} for everyone in this chat.";
"lng_delete_for_me_chat_hint" = "This will delete {count:_not_used_|it|them} just for you, not for other participants of the chat.";
"lng_delete_for_me_hint" = "This will delete {count:_not_used_|it|them} just for you.";
"lng_delete_for_everyone_hint#one" = "This will delete it for everyone in this chat.";
"lng_delete_for_everyone_hint#other" = "This will delete them for everyone in this chat.";
"lng_delete_for_me_chat_hint#one" = "This will delete it just for you, not for other participants of the chat.";
"lng_delete_for_me_chat_hint#other" = "This will delete them just for you, not for other participants of the chat.";
"lng_delete_for_me_hint#one" = "This will delete it just for you.";
"lng_delete_for_me_hint#other" = "This will delete them just for you.";
"lng_delete_for_everyone_check" = "Delete for everyone";
"lng_delete_for_other_check" = "Delete for {user}";
"lng_box_delete" = "Delete";
@ -1061,7 +1133,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_about_text_3" = "Visit {faq_open}Telegram FAQ{faq_close} for more info.";
"lng_about_done" = "Done";
"lng_search_found_results" = "{count:No messages found|Found # message|Found # messages}";
"lng_search_no_results" = "No messages found";
"lng_search_found_results#one" = "Found {count} message";
"lng_search_found_results#other" = "Found {count} messages";
"lng_search_global_results" = "Global search results";
"lng_media_save_progress" = "{ready} of {total} {mb}";

View File

@ -547,14 +547,18 @@ void DeleteMessagesBox::deleteAndClear() {
Ui::hideLayer();
}
ConfirmInviteBox::ConfirmInviteBox(QWidget*, const QString &title, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants)
ConfirmInviteBox::ConfirmInviteBox(QWidget*, const QString &title, bool isChannel, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants)
: _title(this, st::confirmInviteTitle)
, _status(this, st::confirmInviteStatus)
, _participants(participants) {
_title->setText(title);
QString status;
if (_participants.isEmpty() || _participants.size() >= count) {
status = lng_chat_status_members(lt_count, count);
if (count > 0) {
status = lng_chat_status_members(lt_count, count);
} else {
status = lang(isChannel ? lng_channel_status : lng_group_status);
}
} else {
status = lng_group_invite_members(lt_count, count);
}

View File

@ -200,7 +200,7 @@ private:
class ConfirmInviteBox : public BoxContent, public RPCSender {
public:
ConfirmInviteBox(QWidget*, const QString &title, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants);
ConfirmInviteBox(QWidget*, const QString &title, bool isChannel, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants);
protected:
void prepare() override;

View File

@ -898,11 +898,13 @@ ContactsBox::Inner::ContactData *ContactsBox::Inner::contactData(Dialogs::Row *r
data->statusText = App::onlineText(peer->asUser(), _time);
data->statusHasOnlineColor = App::onlineColorUse(peer->asUser(), _time);
} else if (peer->isChat()) {
ChatData *chat = peer->asChat();
auto chat = peer->asChat();
if (!chat->amIn()) {
data->statusText = lang(lng_chat_status_unaccessible);
} else {
} else if (chat->count > 0) {
data->statusText = lng_chat_status_members(lt_count, chat->count);
} else {
data->statusText = lang(lng_group_status);
}
} else if (peer->isMegagroup()) {
data->statusText = lang(lng_group_status);

View File

@ -86,7 +86,11 @@ void LanguageBox::Inner::languageChanged(int languageIndex) {
activateCurrent();
auto languageId = (*_languages)[languageIndex].id;
Lang::CurrentCloudManager().switchToLanguage(languageId);
if (Lang::Current().id() != languageId) {
// "custom" is applied each time it is passed to switchToLanguage().
// So we check that the language really has changed.
Lang::CurrentCloudManager().switchToLanguage(languageId);
}
}
void LanguageBox::Inner::activateCurrent() {

View File

@ -713,9 +713,11 @@ void StickersBox::Inner::paintRow(Painter &p, int index, TimeMs ms) {
}
}
auto statusText = (s->count > 0) ? lng_stickers_count(lt_count, s->count) : lang(lng_contacts_loading);
p.setFont(st::contactsStatusFont);
p.setPen(st::contactsStatusFg);
p.drawTextLeft(statusx, statusy, width(), lng_stickers_count(lt_count, s->count));
p.drawTextLeft(statusx, statusy, width(), statusText);
p.setOpacity(1);
if (xadd || yadd) p.translate(-xadd, -yadd);

View File

@ -676,9 +676,10 @@ void StickersListWidget::paintFeaturedStickers(Painter &p, QRect clip) {
}
}
auto statusText = (size > 0) ? lng_stickers_count(lt_count, size) : lang(lng_contacts_loading);
p.setFont(st::stickersTrendingSubheaderFont);
p.setPen(st::stickersTrendingSubheaderFg);
p.drawTextLeft(st::emojiPanHeaderLeft - st::buttonRadius, y + st::stickersTrendingSubheaderTop, width(), lng_stickers_count(lt_count, size));
p.drawTextLeft(st::emojiPanHeaderLeft - st::buttonRadius, y + st::stickersTrendingSubheaderTop, width(), statusText);
y += st::stickersTrendingHeader;
if (y >= clip.y() + clip.height()) break;

View File

@ -31,8 +31,6 @@ namespace codegen {
namespace lang {
namespace {
constexpr auto kMaxPluralVariants = 6;
char hexChar(uchar ch) {
if (ch < 10) {
return '0' + ch;
@ -120,7 +118,6 @@ bool Generator::writeHeader() {
header_->include("lang/lang_tag.h").newline().pushNamespace("Lang").stream() << "\
\n\
constexpr auto kTagsCount = " << langpack_.tags.size() << ";\n\
constexpr auto kTagsPluralVariants = " << kMaxPluralVariants << ";\n\
\n";
header_->popNamespace().newline();
@ -141,21 +138,26 @@ enum LangKey {\n";
\n\
QString lang(LangKey key);\n\
\n";
for (auto &entry : langpack_.entries) {
if (!entry.tags.empty()) {
auto &key = entry.key;
auto params = QStringList();
auto applyTags = QStringList();
for (auto &tagData : entry.tags) {
auto &tag = tagData.tag;
auto isPlural = isTagPlural(key, tag);
params.push_back("lngtag_" + tag + ", " + (isPlural ? "float64 " : "const QString &") + tag + "__val");
applyTags.push_back("\tresult = Lang::Tag(result, lt_" + tag + ", " + (isPlural ? ("Lang::Plural(" + key + "__" + tag + "0, lt_" + tag + ", " + tag + "__val)") : (tag + "__val")) + ");");
auto isPlural = !entry.keyBase.isEmpty();
auto &key = entry.key;
auto params = QStringList();
auto applyTags = QStringList();
for (auto &tagData : entry.tags) {
auto &tag = tagData.tag;
auto isPluralTag = isPlural && (tag == kPluralTag);
params.push_back("lngtag_" + tag + ", " + (isPluralTag ? "float64 " : "const QString &") + tag + "__val");
if (!isPluralTag) {
applyTags.push_back("\tresult = Lang::Tag(result, lt_" + tag + ", " + tag + "__val);\n");
}
}
if (!entry.tags.empty() && (!isPlural || key == ComputePluralKey(entry.keyBase, 0))) {
auto initialString = isPlural ? ("Lang::Plural(" + key + ", lt_" + kPluralTag + ", " + kPluralTag + "__val)") : ("lang(" + getFullKey(entry) + ")");
header_->stream() << "\
inline QString " << entry.key << "(" << params.join(QString(", ")) << ") {\n\
auto result = lang(" << entry.key << "__tagged);\n\
" << applyTags.join('\n') << ";\n\
inline QString " << (isPlural ? entry.keyBase : key) << "(" << params.join(QString(", ")) << ") {\n\
auto result = " << initialString << ";\n\
" << applyTags.join(QString()) << "\
return result;\n\
}\n\
\n";
@ -167,7 +169,6 @@ inline QString " << entry.key << "(" << params.join(QString(", ")) << ") {\n\
const char *GetKeyName(LangKey key);\n\
ushort GetTagIndex(QLatin1String tag);\n\
LangKey GetKeyIndex(QLatin1String key);\n\
LangKey GetSubkeyIndex(LangKey key, ushort tag, ushort index);\n\
bool IsTagReplaced(LangKey key, ushort tag);\n\
QString GetOriginalValue(LangKey key);\n\
\n";
@ -258,15 +259,19 @@ LangKey GetKeyIndex(QLatin1String key) {\n\
auto taggedKeys = std::map<QString, QString>();
auto keysSet = std::set<QString, std::greater<QString>>();
for (auto &entry : langpack_.entries) {
if (entry.key.mid(0, entry.key.size() - 1).endsWith("__count")) {
continue;
if (!entry.keyBase.isEmpty()) {
for (auto i = 0; i != kPluralPartCount; ++i) {
auto keyName = entry.keyBase + '#' + kPluralParts[i];
taggedKeys.emplace(keyName, ComputePluralKey(entry.keyBase, i));
keysSet.insert(keyName);
}
} else {
auto full = getFullKey(entry);
if (full != entry.key) {
taggedKeys.emplace(entry.key, full);
}
keysSet.insert(entry.key);
}
auto full = getFullKey(entry);
if (full != entry.key) {
taggedKeys.emplace(entry.key, full);
}
keysSet.insert(entry.key);
}
writeSetSearch(keysSet, [&taggedKeys](const QString &key) {
@ -277,44 +282,28 @@ LangKey GetKeyIndex(QLatin1String key) {\n\
source_->stream() << "\
}\n\
\n\
LangKey GetSubkeyIndex(LangKey key, ushort tag, ushort index) {\n\
if (index >= kTagsPluralVariants) return kLangKeysCount;\n\
\n\
switch (key) {\n";
for (auto &entry : langpack_.entries) {
auto cases = QString();
for (auto &tag : entry.tags) {
if (isTagPlural(entry.key, tag.tag)) {
cases += "\t\t\tcase lt_" + tag.tag + ": return LangKey(" + entry.key + "__" + tag.tag + "0 + index);\n";
}
}
if (cases.isEmpty()) {
continue;
}
source_->stream() << "\
case " << entry.key << "__tagged: {\n\
switch (tag) {\n\
" << cases << "\
}\n\
} break;\n";
}
source_->stream() << "\
}\n\
\n\
return kLangKeysCount;\n\
}\n\
\n\
bool IsTagReplaced(LangKey key, ushort tag) {\n\
switch (key) {\n";
auto lastWrittenPluralEntry = QString();
for (auto &entry : langpack_.entries) {
if (entry.tags.empty()) {
continue;
}
if (!entry.keyBase.isEmpty()) {
if (entry.keyBase == lastWrittenPluralEntry) {
continue;
}
lastWrittenPluralEntry = entry.keyBase;
for (auto i = 0; i != kPluralPartCount; ++i) {
source_->stream() << "\
case " << ComputePluralKey(entry.keyBase, i) << ":" << ((i + 1 == kPluralPartCount) ? " {" : "") << "\n";
}
} else {
source_->stream() << "\
case " << getFullKey(entry) << ": {\n";
}
source_->stream() << "\
case " << entry.key << "__tagged: {\n\
switch (tag) {\n";
for (auto &tag : entry.tags) {
source_->stream() << "\
@ -480,21 +469,11 @@ void Generator::writeSetSearch(const std::set<QString, std::greater<QString>> &s
}
QString Generator::getFullKey(const LangPack::Entry &entry) {
if (entry.tags.empty()) {
if (!entry.keyBase.isEmpty() || entry.tags.empty()) {
return entry.key;
}
return entry.key + "__tagged";
}
bool Generator::isTagPlural(const QString &key, const QString &tag) const {
auto searchForKey = key + "__" + tag + "0";
for (auto &entry : langpack_.entries) {
if (entry.key == searchForKey) {
return true;
}
}
return false;
}
} // namespace lang
} // namespace codegen

View File

@ -43,7 +43,6 @@ public:
private:
QString getFullKey(const LangPack::Entry &entry);
bool isTagPlural(const QString &key, const QString &tag) const;
template <typename ComputeResult>
void writeSetSearch(const std::set<QString, std::greater<QString>> &set, ComputeResult computeResult, const QString &invalidResult);

View File

@ -46,7 +46,7 @@ bool ValidateAnsiString(const QString &value) {
}
bool ValidateKey(const QString &key) {
static const auto validator = QRegularExpression("^[a-z0-9_.-]+$", QRegularExpression::CaseInsensitiveOption);
static const auto validator = QRegularExpression("^[a-z0-9_.-]+(#(one|other))?$", QRegularExpression::CaseInsensitiveOption);
if (!validator.match(key).hasMatch()) {
return false;
}
@ -78,6 +78,21 @@ QString PrepareCommandString(int index) {
} // namespace
const std::array<QString, kPluralPartCount> kPluralParts = {
"zero",
"one",
"two",
"few",
"many",
"other",
};
const QString kPluralTag = "count";
QString ComputePluralKey(const QString &base, int index) {
return base + "__plural" + QString::number(index);
}
ParsedFile::ParsedFile(const Options &options)
: filePath_(options.inputPath)
, file_(filePath_)
@ -104,7 +119,7 @@ bool ParsedFile::read() {
logErrorUnexpectedToken() << "'=' for '" << keyToken.value.toStdString() << "' key";
}
} else {
logErrorUnexpectedToken() << "string key name (/^[a-z0-9_.-]+$/i)";
logErrorUnexpectedToken() << "string key name (/^[a-z0-9_.-]+(#(one|other))?$/i)";
}
}
if (file_.atEnd()) {
@ -113,9 +128,46 @@ bool ParsedFile::read() {
logErrorUnexpectedToken() << "ansi string key name";
} while (!failed());
fillPluralTags();
return !failed();
}
void ParsedFile::fillPluralTags() {
auto count = result_.entries.size();
for (auto i = 0; i != count;) {
auto &baseEntry = result_.entries[i];
if (baseEntry.keyBase.isEmpty()) {
++i;
continue;
}
logAssert(i + kPluralPartCount < count);
// Accumulate all tags from all plural variants.
auto tags = std::vector<LangPack::Tag>();
for (auto j = i; j != i + kPluralPartCount; ++j) {
if (tags.empty()) {
tags = result_.entries[j].tags;
} else {
for (auto &tag : result_.entries[j].tags) {
if (std::find(tags.begin(), tags.end(), tag) == tags.end()) {
tags.push_back(tag);
}
}
}
}
logAssert(!tags.empty());
logAssert(tags.front().tag == kPluralTag);
// Set this tags list to all plural variants.
for (auto j = i; j != i + kPluralPartCount; ++j) {
result_.entries[j].tags = tags;
}
i += kPluralPartCount;
}
}
BasicToken ParsedFile::assertNextToken(BasicToken::Type type) {
auto result = file_.getToken(type);
if (!result) {
@ -204,24 +256,85 @@ QString ParsedFile::extractTagData(const QString &tagText, LangPack *to) {
return PrepareCommandString(tagIndex);
}
void ParsedFile::addEntity(const QString &key, const QString &value) {
for (auto &entry : result_.entries) {
if (entry.key == key) {
logError(kErrorBadString) << "duplicate found for key '" << key.toStdString() << "'";
void ParsedFile::addEntity(QString key, const QString &value) {
auto pluralPartOffset = key.indexOf('#');
auto pluralIndex = -1;
if (pluralPartOffset >= 0) {
auto pluralPart = key.mid(pluralPartOffset + 1);
pluralIndex = std::find(kPluralParts.begin(), kPluralParts.end(), pluralPart) - kPluralParts.begin();
if (pluralIndex < 0 || pluralIndex >= kPluralParts.size()) {
logError(kErrorBadString) << "bad plural part for key '" << key.toStdString() << "': '" << pluralPart.toStdString() << "'";
return;
}
key = key.mid(0, pluralPartOffset);
}
auto checkKey = [this](const QString &key) {
for (auto &entry : result_.entries) {
if (entry.key == key) {
if (entry.keyBase.isEmpty() || !entry.tags.empty()) {
// Empty tags in plural entry means it was not encountered yet.
logError(kErrorBadString) << "duplicate found for key '" << key.toStdString() << "'";
return false;
}
}
}
return true;
};
if (!checkKey(key)) {
return;
}
auto tagsData = LangPack();
auto entry = LangPack::Entry();
entry.key = key;
entry.value = extractTagsData(value, &tagsData);
entry.tags = tagsData.tags;
result_.entries.push_back(entry);
for (auto &pluralEntry : tagsData.entries) {
auto taggedEntry = LangPack::Entry();
taggedEntry.key = key + "__" + pluralEntry.key;
taggedEntry.value = pluralEntry.value;
result_.entries.push_back(taggedEntry);
if (pluralIndex >= 0) {
logAssert(tagsData.entries.empty());
entry.keyBase = entry.key;
entry.key = ComputePluralKey(entry.keyBase, pluralIndex);
if (!checkKey(entry.key)) {
return;
}
auto baseIndex = -1;
auto alreadyCount = result_.entries.size();
for (auto i = 0; i != alreadyCount; ++i) {
if (result_.entries[i].keyBase == entry.keyBase) {
// This is not the first appearance of this plural key.
baseIndex = i;
break;
}
}
if (baseIndex < 0) {
baseIndex = result_.entries.size();
for (auto i = 0; i != kPluralPartCount; ++i) {
auto addingEntry = LangPack::Entry();
addingEntry.keyBase = entry.keyBase;
addingEntry.key = ComputePluralKey(entry.keyBase, i);
result_.entries.push_back(addingEntry);
}
}
auto entryIndex = baseIndex + pluralIndex;
logAssert(entryIndex < result_.entries.size());
auto &realEntry = result_.entries[entryIndex];
logAssert(realEntry.key == entry.key);
realEntry.value = entry.value;
// Add all new tags to the existing ones.
realEntry.tags = std::vector<LangPack::Tag>(1, LangPack::Tag { kPluralTag });
for (auto &tag : entry.tags) {
if (std::find(realEntry.tags.begin(), realEntry.tags.end(), tag) == realEntry.tags.end()) {
realEntry.tags.push_back(tag);
}
}
} else {
result_.entries.push_back(entry);
for (auto &pluralEntry : tagsData.entries) {
auto taggedEntry = LangPack::Entry();
taggedEntry.key = key + "__" + pluralEntry.key;
taggedEntry.value = pluralEntry.value;
result_.entries.push_back(taggedEntry);
}
}
}

View File

@ -22,6 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include <memory>
#include <string>
#include <array>
#include <functional>
#include <QImage>
#include "codegen/common/basic_tokenized_file.h"
@ -30,6 +31,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace codegen {
namespace lang {
constexpr auto kPluralPartCount = 6;
extern const std::array<QString, kPluralPartCount> kPluralParts;
extern const QString kPluralTag;
QString ComputePluralKey(const QString &base, int index);
struct LangPack {
struct Tag {
QString tag;
@ -37,6 +43,7 @@ struct LangPack {
struct Entry {
QString key;
QString value;
QString keyBase; // Empty for not plural entries.
std::vector<Tag> tags;
};
std::vector<Entry> entries;
@ -44,6 +51,14 @@ struct LangPack {
};
inline bool operator==(const LangPack::Tag &a, const LangPack::Tag &b) {
return a.tag == b.tag;
}
inline bool operator!=(const LangPack::Tag &a, const LangPack::Tag &b) {
return !(a == b);
}
// Parses an input file to the internal struct.
class ParsedFile {
public:
@ -83,10 +98,12 @@ private:
using BasicToken = common::BasicTokenizedFile::Token;
BasicToken assertNextToken(BasicToken::Type type);
void addEntity(const QString &key, const QString &value);
void addEntity(QString key, const QString &value);
QString extractTagsData(const QString &value, LangPack *to);
QString extractTagData(const QString &tag, LangPack *to);
void fillPluralTags();
QString filePath_;
common::BasicTokenizedFile file_;
Options options_;

View File

@ -326,7 +326,7 @@ void DialogsInner::paintRegion(Painter &p, const QRegion &region, bool paintingO
}
if (_state == SearchedState || !_searchResults.empty()) {
QString text = lng_search_found_results(lt_count, _searchResults.empty() ? 0 : (_searchedMigratedCount + _searchedCount));
auto text = _searchResults.empty() ? lang(lng_search_no_results) : lng_search_found_results(lt_count, _searchedMigratedCount + _searchedCount);
p.fillRect(0, 0, fullWidth, st::searchedBarHeight, st::searchedBarBg);
if (!paintingOther) {
p.setFont(st::searchedBarFont);

View File

@ -2158,9 +2158,9 @@ HistoryService::PreparedText HistoryService::prepareGameScoreText() {
result.links.push_back(fromLink());
auto gameTitle = computeGameTitle();
if (gameTitle.isEmpty()) {
result.text = lng_action_game_score_no_game(lt_from, fromLinkText(), lt_count, scoreNumber);
result.text = lng_action_game_score_no_game(lt_count, scoreNumber, lt_from, fromLinkText());
} else {
result.text = lng_action_game_score(lt_from, fromLinkText(), lt_count, scoreNumber, lt_game, gameTitle);
result.text = lng_action_game_score(lt_count, scoreNumber, lt_from, fromLinkText(), lt_game, gameTitle);
}
}
return result;

View File

@ -4031,24 +4031,34 @@ void HistoryWidget::updateOnlineDisplay() {
text = App::onlineText(user, t);
titlePeerTextOnline = App::onlineColorUse(user, t);
} else if (_peer->isChat()) {
ChatData *chat = _peer->asChat();
auto chat = _peer->asChat();
if (!chat->amIn()) {
text = lang(lng_chat_status_unaccessible);
} else if (chat->participants.isEmpty()) {
text = _titlePeerText.isEmpty() ? lng_chat_status_members(lt_count, chat->count < 0 ? 0 : chat->count) : _titlePeerText;
if (!_titlePeerText.isEmpty()) {
text = _titlePeerText;
} else if (chat->count <= 0) {
text = lang(lng_group_status);
} else {
text = lng_chat_status_members(lt_count, chat->count);
}
} else {
int32 onlineCount = 0;
bool onlyMe = true;
for (ChatData::Participants::const_iterator i = chat->participants.cbegin(), e = chat->participants.cend(); i != e; ++i) {
auto online = 0;
auto onlyMe = true;
for (auto i = chat->participants.cbegin(), e = chat->participants.cend(); i != e; ++i) {
if (i.key()->onlineTill > t) {
++onlineCount;
++online;
if (onlyMe && i.key() != App::self()) onlyMe = false;
}
}
if (onlineCount && !onlyMe) {
text = lng_chat_status_members_online(lt_count, chat->participants.size(), lt_count_online, onlineCount);
} else {
if (online > 0 && !onlyMe) {
auto membersCount = lng_chat_status_members(lt_count, chat->participants.size());
auto onlineCount = lng_chat_status_online(lt_count, online);
text = lng_chat_status_members_online(lt_members_count, membersCount, lt_online_count, onlineCount);
} else if (chat->participants.size() > 0) {
text = lng_chat_status_members(lt_count, chat->participants.size());
} else {
text = lang(lng_group_status);
}
}
} else if (_peer->isChannel()) {
@ -4056,21 +4066,27 @@ void HistoryWidget::updateOnlineDisplay() {
if (_peer->asChannel()->mgInfo->lastParticipants.size() < _peer->asChannel()->membersCount() || _peer->asChannel()->lastParticipantsCountOutdated()) {
if (App::api()) App::api()->requestLastParticipants(_peer->asChannel());
}
int32 onlineCount = 0;
auto online = 0;
bool onlyMe = true;
for (auto i = _peer->asChannel()->mgInfo->lastParticipants.cbegin(), e = _peer->asChannel()->mgInfo->lastParticipants.cend(); i != e; ++i) {
if ((*i)->onlineTill > t) {
++onlineCount;
++online;
if (onlyMe && (*i) != App::self()) onlyMe = false;
}
}
if (onlineCount && !onlyMe) {
text = lng_chat_status_members_online(lt_count, _peer->asChannel()->membersCount(), lt_count_online, onlineCount);
} else {
if (online && !onlyMe) {
auto membersCount = lng_chat_status_members(lt_count, _peer->asChannel()->membersCount());
auto onlineCount = lng_chat_status_online(lt_count, online);
text = lng_chat_status_members_online(lt_members_count, membersCount, lt_online_count, onlineCount);
} else if (_peer->asChannel()->membersCount() > 0) {
text = lng_chat_status_members(lt_count, _peer->asChannel()->membersCount());
} else {
text = lang(lng_group_status);
}
} else if (_peer->asChannel()->membersCount() > 0) {
text = lng_chat_status_members(lt_count, _peer->asChannel()->membersCount());
} else {
text = _peer->asChannel()->membersCount() ? lng_chat_status_members(lt_count, _peer->asChannel()->membersCount()) : lang(_peer->isMegagroup() ? lng_group_status : lng_channel_status);
text = lang(_peer->isMegagroup() ? lng_group_status : lng_channel_status);
}
}
if (_titlePeerText != text) {

View File

@ -256,17 +256,18 @@ void Widget::resetAccount() {
auto type = error.type();
if (type.startsWith(qstr("2FA_CONFIRM_WAIT_"))) {
int seconds = type.mid(qstr("2FA_CONFIRM_WAIT_").size()).toInt();
int days = (seconds + 59) / 86400;
int hours = ((seconds + 59) % 86400) / 3600;
int minutes = ((seconds + 59) % 3600) / 60;
QString when;
auto seconds = type.mid(qstr("2FA_CONFIRM_WAIT_").size()).toInt();
auto days = (seconds + 59) / 86400;
auto hours = ((seconds + 59) % 86400) / 3600;
auto minutes = ((seconds + 59) % 3600) / 60;
auto when = lng_signin_reset_minutes(lt_count, minutes);
if (days > 0) {
when = lng_signin_reset_in_days(lt_count_days, days, lt_count_hours, hours, lt_count_minutes, minutes);
auto daysCount = lng_signin_reset_days(lt_count, days);
auto hoursCount = lng_signin_reset_hours(lt_count, hours);
when = lng_signin_reset_in_days(lt_days_count, daysCount, lt_hours_count, hoursCount, lt_minutes_count, when);
} else if (hours > 0) {
when = lng_signin_reset_in_hours(lt_count_hours, hours, lt_count_minutes, minutes);
} else {
when = lng_signin_reset_in_minutes(lt_count_minutes, minutes);
auto hoursCount = lng_signin_reset_hours(lt_count, hours);
when = lng_signin_reset_in_hours(lt_hours_count, hoursCount, lt_minutes_count, when);
}
Ui::show(Box<InformBox>(lng_signin_reset_wait(lt_phone_number, App::formatPhone(getData()->phone), lt_when, when)));
} else if (type == qstr("2FA_RECENT_CONFIRM")) {

View File

@ -196,7 +196,7 @@ void CloudManager::switchToLanguage(QString id) {
if (id.isEmpty()) {
id = DefaultLanguageId();
}
if (_langpack.id() == id) {
if (_langpack.id() == id && id != qstr("custom")) {
return;
}

View File

@ -78,7 +78,7 @@ bool FileParser::readKeyValue(const char *&from, const char *end) {
}
++from;
const char *nameStart = from;
while (from < end && ((*from >= 'a' && *from <= 'z') || (*from >= 'A' && *from <= 'Z') || *from == '_' || (*from >= '0' && *from <= '9'))) {
while (from < end && ((*from >= 'a' && *from <= 'z') || (*from >= 'A' && *from <= 'Z') || *from == '_' || (*from >= '0' && *from <= '9') || *from == '#')) {
++from;
}

View File

@ -26,6 +26,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "platform/platform_specific.h"
#include "boxes/confirm_box.h"
#include "lang/lang_file_parser.h"
#include "base/qthelp_regex.h"
namespace Lang {
namespace {
@ -43,6 +44,10 @@ constexpr str_const kLegacyLanguages[] = {
"ko",
};
QString ConvertLegacyLanguageId(const QString &languageId) {
return languageId.toLower().replace('_', '-');
}
class ValueParser {
public:
ValueParser(const QByteArray &key, LangKey keyIndex, const QByteArray &value);
@ -51,17 +56,11 @@ public:
Expects(!_failed);
return std::move(_result);
}
std::map<LangKey, QString> takePluralValues() {
Expects(!_failed);
return std::move(_plural);
}
bool parse();
private:
void appendToResult(const char *nextBegin);
void appendToPlural(const char *nextBegin);
bool feedPluralValue();
bool logError(const QString &text);
bool readTag();
@ -72,16 +71,11 @@ private:
ushort _currentTagIndex = 0;
QString _currentTagReplacer;
QString _pluralValue;
int _pluralIndex = 0;
bool _pluralNumericFound = false;
bool _failed = true;
const char *_begin, *_ch, *_end;
QString _result;
std::map<LangKey, QString> _plural;
OrderedSet<ushort> _tagsUsed;
};
@ -99,29 +93,6 @@ void ValueParser::appendToResult(const char *nextBegin) {
_begin = nextBegin;
}
void ValueParser::appendToPlural(const char *nextBegin) {
if (_ch > _begin) _pluralValue.append(QString::fromUtf8(_begin, _ch - _begin));
_begin = nextBegin;
}
bool ValueParser::feedPluralValue() {
appendToPlural(_ch + 1);
if (_pluralIndex >= kTagsPluralVariants) {
return logError("Too many values inside counted tag");
}
auto pluralKeyIndex = GetSubkeyIndex(_keyIndex, _currentTagIndex, _pluralIndex);
if (pluralKeyIndex == kLangKeysCount) {
return logError("Unexpected counted tag");
} else {
_plural.emplace(pluralKeyIndex, _pluralValue);
}
++_pluralIndex;
_pluralValue = QString();
_pluralNumericFound = false;
return true;
};
bool ValueParser::logError(const QString &text) {
_failed = true;
auto loggedKey = (_currentTag.size() > 0) ? (_key + QString(':') + _currentTag) : QString(_key);
@ -149,8 +120,8 @@ bool ValueParser::readTag() {
}
_currentTag = QLatin1String(tagStart, _ch - tagStart);
if (_ch == _end || (*_ch != '}' && *_ch != ':')) {
return logError("Expected '}' or ':' after tag name");
if (_ch == _end || *_ch != '}') {
return logError("Expected '}' after tag name");
}
_currentTagIndex = GetTagIndex(_currentTag);
@ -189,39 +160,6 @@ bool ValueParser::parse() {
_result.append(_currentTagReplacer);
_begin = _ch + 1;
if (*_ch == ':') {
_pluralIndex = 0;
while (_ch != _end && *_ch != '}') {
if (*_ch == '|') {
if (!feedPluralValue()) {
return false;
}
} else if (*_ch == '\\') {
if (_ch + 1 >= _end) {
return logError("Unexpected end of file inside counted tag");
}
if (*(_ch + 1) == '{' || *(_ch + 1) == '#' || *(_ch + 1) == '}') {
appendToPlural(_ch + 1);
}
} else if (*_ch == '{') {
return logError("Unexpected tag inside counted tag");
} else if (*_ch == '#') {
if (_pluralNumericFound) {
return logError("Replacement '#' double used inside counted tag");
}
_pluralNumericFound = true;
appendToPlural(_ch + 1);
_pluralValue.append(_currentTagReplacer);
}
++_ch;
}
if (_ch == _end) {
return logError("Unexpected end of value inside counted tag");
}
if (!feedPluralValue()) {
return false;
}
}
_currentTag = QLatin1String();
}
}
@ -259,6 +197,7 @@ void Instance::switchToId(const QString &id) {
}
_updated.notify();
}
updatePluralRules();
}
void Instance::switchToCustomFile(const QString &filePath) {
@ -271,6 +210,7 @@ void Instance::switchToCustomFile(const QString &filePath) {
void Instance::reset() {
_values.clear();
_nonDefaultValues.clear();
_nonDefaultSet.clear();
_legacyId = kLegacyLanguageNone;
_customFilePathAbsolute = QString();
_customFilePathRelative = QString();
@ -286,6 +226,7 @@ void Instance::fillDefaults() {
for (auto i = 0; i != kLangKeysCount; ++i) {
_values.emplace_back(GetOriginalValue(LangKey(i)));
}
_nonDefaultSet = std::vector<uchar>(kLangKeysCount, 0);
}
QString Instance::systemLangCode() const {
@ -388,6 +329,7 @@ void Instance::fillFromSerialized(const QByteArray &data) {
for (auto i = 0, count = nonDefaultValuesCount * 2; i != count; i += 2) {
applyValue(nonDefaultStrings[i], nonDefaultStrings[i + 1]);
}
updatePluralRules();
}
void Instance::loadFromContent(const QByteArray &content) {
@ -416,6 +358,7 @@ void Instance::fillFromCustomFile(const QString &filePath) {
auto content = Lang::FileParser::ReadFile(absolutePath, relativePath);
if (!content.isEmpty()) {
loadFromCustomContent(absolutePath, relativePath, content);
updatePluralRules();
}
}
@ -441,6 +384,8 @@ void Instance::fillFromLegacy(int legacyId, const QString &legacyPath) {
loadFromContent(content);
}
}
_id = ConvertLegacyLanguageId(_id);
updatePluralRules();
}
template <typename SetCallback, typename ResetCallback>
@ -508,25 +453,41 @@ std::map<LangKey, QString> Instance::ParseStrings(const MTPVector<MTPLangPackStr
}
template <typename Result>
void Instance::ParseKeyValue(const QByteArray &key, const QByteArray &value, Result &result) {
LangKey Instance::ParseKeyValue(const QByteArray &key, const QByteArray &value, Result &result) {
auto keyIndex = GetKeyIndex(QLatin1String(key));
if (keyIndex == kLangKeysCount) {
LOG(("Lang Error: Unknown key '%1'").arg(QString::fromLatin1(key)));
return;
return kLangKeysCount;
}
ValueParser parser(key, keyIndex, value);
if (parser.parse()) {
result[keyIndex] = parser.takeResult();
for (auto &plural : parser.takePluralValues()) {
result[plural.first] = plural.second;
}
return keyIndex;
}
return kLangKeysCount;
}
void Instance::applyValue(const QByteArray &key, const QByteArray &value) {
_nonDefaultValues[key] = value;
ParseKeyValue(key, value, _values);
auto index = ParseKeyValue(key, value, _values);
if (index != kLangKeysCount) {
_nonDefaultSet[index] = 1;
}
}
void Instance::updatePluralRules() {
auto id = _id;
if (isCustom()) {
auto path = _customFilePathAbsolute.isEmpty() ? _customFilePathRelative : _customFilePathAbsolute;
auto name = QFileInfo(path).fileName();
if (auto match = qthelp::regex_match("_([a-z]{2,3})(_[A-Z]{2,3}|\\-[a-z]{2,3})?\\.", name)) {
id = match->captured(1);
}
} else if (auto match = qthelp::regex_match("^([a-z]{2,3})(_[A-Z]{2,3}|\\-[a-z]{2,3})$", id)) {
id = match->captured(1);
}
UpdatePluralRules(id);
}
void Instance::resetValue(const QByteArray &key) {

View File

@ -75,6 +75,11 @@ public:
Expects(_values.size() == kLangKeysCount);
return _values[key];
}
bool isNonDefaultPlural(LangKey key) {
Expects(key >= 0 && key < kLangKeysCount);
Expects(_nonDefaultSet.size() == kLangKeysCount);
return _nonDefaultSet[key] || _nonDefaultSet[key + 1] || _nonDefaultSet[key + 2] || _nonDefaultSet[key + 3] || _nonDefaultSet[key + 4] || _nonDefaultSet[key + 5];
}
private:
// SetCallback takes two QByteArrays: key, value.
@ -85,7 +90,7 @@ private:
// Writes each key-value pair in the result container.
template <typename Result>
static void ParseKeyValue(const QByteArray &key, const QByteArray &value, Result &result);
static LangKey ParseKeyValue(const QByteArray &key, const QByteArray &value, Result &result);
void applyValue(const QByteArray &key, const QByteArray &value);
void resetValue(const QByteArray &key);
@ -94,6 +99,7 @@ private:
void fillFromCustomFile(const QString &filePath);
void loadFromContent(const QByteArray &content);
void loadFromCustomContent(const QString &absolutePath, const QString &relativePath, const QByteArray &content);
void updatePluralRules();
QString _id;
int _legacyId = kLegacyLanguageNone;
@ -106,6 +112,7 @@ private:
mutable QString _systemLanguage;
std::vector<QString> _values;
std::vector<uchar> _nonDefaultSet;
std::map<QByteArray, QByteArray> _nonDefaultValues;
};

View File

@ -23,6 +23,111 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "lang/lang_keys.h"
namespace Lang {
namespace {
//
// http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html
//
constexpr auto kShiftZero = ushort(0);
constexpr auto kShiftOne = ushort(1);
constexpr auto kShiftTwo = ushort(2);
constexpr auto kShiftFew = ushort(3);
constexpr auto kShiftMany = ushort(4);
constexpr auto kShiftOther = ushort(5);
//
// n absolute value of the source number (integer and decimals).
// i integer digits of n.
// v number of visible fraction digits in n, with trailing zeros.
// w number of visible fraction digits in n, without trailing zeros.
// f visible fractional digits in n, with trailing zeros.
// t visible fractional digits in n, without trailing zeros.
//
// Let n be int, being -1 for non-integer numbers and n == i for integer numbers.
// It is fine while in the rules we compare n only to integers.
//
// -123.450: n = -1, i = 123, v = 3, w = 2, f = 450, t = 45
//
using ChoosePluralMethod = ushort (*)(int n, int i, int v, int w, int f, int t);
ushort ChoosePluralAr(int n, int i, int v, int w, int f, int t) {
if (n == 0) {
return kShiftZero;
} else if (n == 1) {
return kShiftOne;
} else if (n == 2) {
return kShiftTwo;
} else if (n < 0) {
return kShiftOther;
}
auto mod100 = (n % 100);
if (mod100 >= 3 && mod100 <= 10) {
return kShiftFew;
} else if (mod100 >= 11 && mod100 <= 99) {
return kShiftMany;
}
return kShiftOther;
}
ushort ChoosePluralEn(int n, int i, int v, int w, int f, int t) {
if (i == 1 && v == 0) {
return kShiftOne;
}
return kShiftOther;
}
ushort ChoosePluralPt(int n, int i, int v, int w, int f, int t) {
if (i == 0 || i == 1) {
return kShiftOne;
}
return kShiftOther;
}
ushort ChoosePluralEs(int n, int i, int v, int w, int f, int t) {
if (n == 1) {
return kShiftOne;
}
return kShiftOther;
}
ushort ChoosePluralKo(int n, int i, int v, int w, int f, int t) {
return kShiftOther;
}
ushort ChoosePluralRu(int n, int i, int v, int w, int f, int t) {
if (v == 0) {
auto mod10 = (i % 10);
auto mod100 = (i % 100);
if ((mod10 == 1) && (mod100 != 11)) {
return kShiftOne;
} else if ((mod10 >= 2) && (mod10 <= 4) && (mod100 < 12 || mod100 > 14)) {
return kShiftFew;
} else {
return kShiftMany;
}
}
return kShiftMany;// kShiftOther;
}
QMap<QString, ChoosePluralMethod> GeneratePluralRulesMap() {
auto result = QMap<QString, ChoosePluralMethod>();
result.insert(qsl("ar"), ChoosePluralAr);
// result.insert(qsl("de"), ChoosePluralEn);
// result.insert(qsl("en"), ChoosePluralEn); // En is default, so we don't fill it inside the map.
result.insert(qsl("es"), ChoosePluralEs);
// result.insert(qsl("it"), ChoosePluralEn);
result.insert(qsl("ko"), ChoosePluralKo);
// result.insert(qsl("nl"), ChoosePluralEn);
result.insert(qsl("pt"), ChoosePluralPt);
result.insert(qsl("ru"), ChoosePluralRu);
return result;
}
ChoosePluralMethod ChoosePlural = ChoosePluralEn;
} // namespace
QString Tag(const QString &original, ushort tag, const QString &replacement) {
for (auto s = original.constData(), ch = s, e = ch + original.size(); ch != e;) {
@ -53,29 +158,29 @@ QString Tag(const QString &original, ushort tag, const QString &replacement) {
return original;
}
QString Plural(ushort key0, ushort tag, float64 value) { // current lang dependent
int v = qFloor(value);
QString sv;
ushort key = key0;
if (v != qCeil(value)) {
key += 2;
sv = QString::number(value);
} else {
if (v == 1) {
key += 1;
} else if (v) {
key += 2;
}
sv = QString::number(v);
QString Plural(ushort keyBase, ushort tag, float64 value) {
// Simplified.
auto n = qAbs(value);
auto i = qFloor(n);
auto integer = (qCeil(n) == i);
auto v = integer ? 0 : 6;
auto w = v;
auto f = integer ? 0 : 111111;
auto t = integer ? 0 : 111111;
auto &langpack = Lang::Current();
auto useNonDefaultPlural = (ChoosePlural != ChoosePluralEn && langpack.isNonDefaultPlural(LangKey(keyBase)));
auto shift = (useNonDefaultPlural ? ChoosePlural : ChoosePluralEn)((integer ? i : -1), i, v, w, f, t);
auto string = langpack.getValue(LangKey(keyBase + shift));
if (i == qCeil(n)) {
return Tag(string, tag, QString::number(value));
}
while (key > key0) {
auto v = lang(LangKey(key));
if (!v.isEmpty()) {
return Tag(v, tag, sv);
}
--key;
}
return Tag(lang(LangKey(key0)), tag, sv);
return Tag(string, tag, QString::number(qRound(value)));
}
void UpdatePluralRules(const QString &languageId) {
static auto kMap = GeneratePluralRulesMap();
ChoosePlural = kMap.value(languageId.toLower(), ChoosePluralEn);
}
} // namespace Lang

View File

@ -23,6 +23,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace Lang {
QString Tag(const QString &original, ushort tag, const QString &replacement);
QString Plural(ushort key0, ushort tag, float64 value);
QString Plural(ushort keyBase, ushort tag, float64 value);
void UpdatePluralRules(const QString &languageId);
} // namespace Lang

View File

@ -130,8 +130,10 @@ QString formatDurationText(qint64 duration) {
QString formatDurationWords(qint64 duration) {
if (duration > 59) {
auto minutes = (duration / 60);
auto minutesCount = lng_duration_minsec_minutes(lt_count, minutes);
auto seconds = (duration % 60);
return lng_duration_minutes_seconds(lt_count_minutes, minutes, lt_count_seconds, seconds);
auto secondsCount = lng_duration_minsec_seconds(lt_count, seconds);
return lng_duration_minutes_seconds(lt_minutes_count, minutesCount, lt_seconds_count, secondsCount);
}
return lng_duration_seconds(lt_count, duration);
}

View File

@ -617,7 +617,7 @@ void MainWidget::updateForwardingTexts() {
version += from->nameVersion;
}
if (fromUsers.size() > 2) {
from = lng_forwarding_from(lt_user, fromUsers.at(0)->shortName(), lt_count, fromUsers.size() - 1);
from = lng_forwarding_from(lt_count, fromUsers.size() - 1, lt_user, fromUsers.at(0)->shortName());
} else if (fromUsers.size() < 2) {
from = fromUsers.at(0)->name;
} else {
@ -4307,7 +4307,7 @@ bool MainWidget::usernameResolveFail(QString name, const RPCError &error) {
void MainWidget::inviteCheckDone(QString hash, const MTPChatInvite &invite) {
switch (invite.type()) {
case mtpc_chatInvite: {
auto &d(invite.c_chatInvite());
auto &d = invite.c_chatInvite();
QVector<UserData*> participants;
if (d.has_participants()) {
@ -4320,7 +4320,8 @@ void MainWidget::inviteCheckDone(QString hash, const MTPChatInvite &invite) {
}
}
_inviteHash = hash;
Ui::show(Box<ConfirmInviteBox>(qs(d.vtitle), d.vphoto, d.vparticipants_count.v, participants));
auto isChannel = d.is_channel() && !d.is_megagroup();
Ui::show(Box<ConfirmInviteBox>(qs(d.vtitle), isChannel, d.vphoto, d.vparticipants_count.v, participants));
} break;
case mtpc_chatInviteAlready: {

View File

@ -810,7 +810,7 @@ void OverviewInner::paintEvent(QPaintEvent *e) {
} else if (_inSearch && _searchResults.isEmpty() && _searchFull && (!_migrated || _searchFullMigrated) && !_searchTimer.isActive()) {
p.setFont(st::noContactsFont->f);
p.setPen(st::noContactsColor->p);
p.drawText(QRect(_rowsLeft, _marginTop, _rowWidth, _marginTop), lng_search_found_results(lt_count, 0), style::al_center);
p.drawText(QRect(_rowsLeft, _marginTop, _rowWidth, _marginTop), lang(lng_search_no_results), style::al_center);
return;
}

View File

@ -373,23 +373,29 @@ void CoverWidget::refreshStatusText() {
}
_cancelPhotoUpload.destroy();
int currentTime = unixtime();
auto currentTime = unixtime();
if (_peerUser) {
_statusText = App::onlineText(_peerUser, currentTime, true);
_statusTextIsOnline = App::onlineColorUse(_peerUser, currentTime);
} else if (_peerChat && _peerChat->amIn()) {
int fullCount = qMax(_peerChat->count, _peerChat->participants.size());
auto fullCount = qMax(_peerChat->count, _peerChat->participants.size());
if (_onlineCount > 0 && _onlineCount <= fullCount) {
_statusText = lng_chat_status_members_online(lt_count, fullCount, lt_count_online, _onlineCount);
} else {
auto membersCount = lng_chat_status_members(lt_count, fullCount);
auto onlineCount = lng_chat_status_online(lt_count, _onlineCount);
_statusText = lng_chat_status_members_online(lt_members_count, membersCount, lt_online_count, onlineCount);
} else if (_peerChat->count > 0) {
_statusText = lng_chat_status_members(lt_count, _peerChat->count);
} else {
_statusText = lang(lng_group_status);
}
} else if (_peerChannel) {
int fullCount = _peerChannel->membersCount();
auto fullCount = _peerChannel->membersCount();
if (_onlineCount > 0 && _onlineCount <= fullCount) {
_statusText = lng_chat_status_members_online(lt_count, fullCount, lt_count_online, _onlineCount);
} else if (fullCount > 0 ) {
_statusText = lng_chat_status_members(lt_count, _peerChannel->membersCount());
auto membersCount = lng_chat_status_members(lt_count, fullCount);
auto onlineCount = lng_chat_status_online(lt_count, _onlineCount);
_statusText = lng_chat_status_members_online(lt_members_count, membersCount, lt_online_count, onlineCount);
} else if (fullCount > 0) {
_statusText = lng_chat_status_members(lt_count, fullCount);
} else {
_statusText = lang(_peerChannel->isMegagroup() ? lng_group_status : lng_channel_status);
}

View File

@ -236,8 +236,8 @@ QString LastSeenPrivacyController::warning() {
QString LastSeenPrivacyController::exceptionLinkText(Exception exception, int count) {
switch (exception) {
case Exception::Always: return lng_edit_privacy_lastseen_always(lt_count, count);
case Exception::Never: return lng_edit_privacy_lastseen_never(lt_count, count);
case Exception::Always: return (count > 0) ? lng_edit_privacy_lastseen_always(lt_count, count) : lang(lng_edit_privacy_lastseen_always_empty);
case Exception::Never: return (count > 0) ? lng_edit_privacy_lastseen_never(lt_count, count) : lang(lng_edit_privacy_lastseen_never_empty);
}
Unexpected("Invalid exception value.");
}
@ -290,8 +290,8 @@ QString GroupsInvitePrivacyController::description() {
QString GroupsInvitePrivacyController::exceptionLinkText(Exception exception, int count) {
switch (exception) {
case Exception::Always: return lng_edit_privacy_groups_always(lt_count, count);
case Exception::Never: return lng_edit_privacy_groups_never(lt_count, count);
case Exception::Always: return (count > 0) ? lng_edit_privacy_groups_always(lt_count, count) : lang(lng_edit_privacy_groups_always_empty);
case Exception::Never: return (count > 0) ? lng_edit_privacy_groups_never(lt_count, count) : lang(lng_edit_privacy_groups_never_empty);
}
Unexpected("Invalid exception value.");
}
@ -322,8 +322,8 @@ QString CallsPrivacyController::description() {
QString CallsPrivacyController::exceptionLinkText(Exception exception, int count) {
switch (exception) {
case Exception::Always: return lng_edit_privacy_calls_always(lt_count, count);
case Exception::Never: return lng_edit_privacy_calls_never(lt_count, count);
case Exception::Always: return (count > 0) ? lng_edit_privacy_calls_always(lt_count, count) : lang(lng_edit_privacy_calls_always_empty);
case Exception::Never: return (count > 0) ? lng_edit_privacy_calls_never(lt_count, count) : lang(lng_edit_privacy_calls_never_empty);
}
Unexpected("Invalid exception value.");
}

View File

@ -65,7 +65,7 @@
'<(PRODUCT_DIR)/codegen_style<(exe_ext)',
'-I', '<(res_loc)', '-I', '<(src_loc)',
'-o', '<(SHARED_INTERMEDIATE_DIR)/styles',
'-w', '<(PRODUCT_DIR)/../..',
'-w', '<(PRODUCT_DIR)/..',
# GYP/Ninja bug workaround: if we specify just <(RULE_INPUT_PATH)
# the <(RULE_INPUT_ROOT) variables won't be available in Ninja,
@ -90,7 +90,7 @@
'action': [
'<(PRODUCT_DIR)/codegen_lang<(exe_ext)',
'-o', '<(SHARED_INTERMEDIATE_DIR)', '<(res_loc)/langs/lang.strings',
'-w', '<(PRODUCT_DIR)/../..',
'-w', '<(PRODUCT_DIR)/..',
],
'message': 'codegen_lang-ing lang.strings..',
'process_outputs_as_sources': 1,
@ -107,7 +107,7 @@
'action': [
'<(PRODUCT_DIR)/codegen_numbers<(exe_ext)',
'-o', '<(SHARED_INTERMEDIATE_DIR)', '<(res_loc)/numbers.txt',
'-w', '<(PRODUCT_DIR)/../..',
'-w', '<(PRODUCT_DIR)/..',
],
'message': 'codegen_numbers-ing numbers.txt..',
'process_outputs_as_sources': 1,
@ -158,7 +158,7 @@
'<(PRODUCT_DIR)/codegen_style<(exe_ext)',
'-I', '<(res_loc)', '-I', '<(src_loc)',
'-o', '<(SHARED_INTERMEDIATE_DIR)/styles',
'-w', '<(PRODUCT_DIR)/../..',
'-w', '<(PRODUCT_DIR)/..',
# GYP/Ninja bug workaround: if we specify just <(RULE_INPUT_PATH)
# the <(RULE_INPUT_ROOT) variables won't be available in Ninja,