Skip to content

Commit

Permalink
Added localization into iOS share extension (mattermost#7351)
Browse files Browse the repository at this point in the history
  • Loading branch information
Partizann authored Jun 21, 2023
1 parent cffe80b commit cc2728a
Show file tree
Hide file tree
Showing 41 changed files with 495 additions and 70 deletions.
13 changes: 8 additions & 5 deletions app/utils/file/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -495,11 +495,14 @@ export const hasWriteStoragePermission = async (intl: IntlShape) => {
},
{applicationName},
);
const text = intl.formatMessage({
id: 'mobile.write_storage_permission_denied_description',
defaultMessage:
'Save files to your device. Open Settings to grant {applicationName} write access to files on this device.',
});
const text = intl.formatMessage(
{
id: 'mobile.write_storage_permission_denied_description',
defaultMessage:
'Save files to your device. Open Settings to grant {applicationName} write access to files on this device.',
},
{applicationName},
);

Alert.alert(title, text, [
{
Expand Down
6 changes: 5 additions & 1 deletion assets/base/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -952,15 +952,19 @@
"settings.save": "Save",
"share_extension.channel_error": "You are not a member of a team on the selected server. Select another server or open Mattermost to join a team.",
"share_extension.channel_label": "Channel",
"share_extension.channels_screen.title": "Select channel",
"share_extension.count_limit": "You can only share {count, number} {count, plural, one {file} other {files}} on this server",
"share_extension.error_screen.description": "There was an error when attempting to share the content to {applicationName}.",
"share_extension.error_screen.label": "An error ocurred",
"share_extension.error_screen.reason": "Reason: {reason}",
"share_extension.file_limit.multiple": "Each file must be less than {size}",
"share_extension.file_limit.single": "File must be less than {size}",
"share_extension.max_resolution": "Image exceeds maximum dimensions of 7680 x 4320 px",
"share_extension.message": "Enter a message (optional)",
"share_extension.multiple_label": "{count, number} attachments",
"share_extension.server_label": "Server",
"share_extension.servers_screen.title": "Select server",
"share_extension.share_screen.title": "Share to Mattermost",
"share_extension.share_screen.title": "Share to {applicationName}",
"share_extension.upload_disabled": "File uploads are disabled for the selected server",
"share_feedback.button.no": "No, thanks",
"share_feedback.button.yes": "Yes",
Expand Down
19 changes: 16 additions & 3 deletions fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -415,14 +415,20 @@ platform :ios do
end

lane :update_identifiers do
# Set the name for the app
# Set the name for the app and share extension
app_name = ENV['APP_NAME'] || 'Mattermost Beta'
update_info_plist(
xcodeproj: './ios/Mattermost.xcodeproj',
plist_path: 'Mattermost/Info.plist',
display_name: app_name
)

update_info_plist(
xcodeproj: './ios/Mattermost.xcodeproj',
plist_path: 'MattermostShare/Info.plist',
display_name: app_name
)

# Set the notification service extension bundle identifier
notification_bundle_id = ENV['NOTIFICATION_SERVICE_IDENTIFIER'] || 'com.mattermost.rnbeta.NotificationService'
update_app_identifier(
Expand Down Expand Up @@ -563,20 +569,27 @@ platform :ios do
json = JSON.parse(localization_file)

plist_strings = ''
localized_strings = ''
json.each do |key, value|
if key.match?('mobile.ios.plist')
unless value.nil? || value.empty?
unless value.nil? || value.empty?
if key.match?('mobile.ios.plist')
plist_strings.concat("#{key.split('.').last} = \"#{value}\";\n")
else
value.gsub!('\\', '\\\\\\\\') # How to replace backslash with double backslash https://stackoverflow.com/a/6209532
value.gsub!('"', '\"')
localized_strings.concat("\"#{key}\" = \"#{value}\";\n")
end
end
end

plist_strings.gsub!('{applicationName}', "#{app_name}")
localized_strings.gsub!('{applicationName}', "#{app_name}")

language = item.split('.').first
project_localization_path = "../ios/Mattermost/i18n/#{language}.lproj"
FileUtils.mkdir_p project_localization_path
File.write("#{project_localization_path}/InfoPlist.strings", plist_strings)
File.write("#{project_localization_path}/Localizable.strings", localized_strings)
end
end

Expand Down
272 changes: 268 additions & 4 deletions ios/Mattermost.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
5 changes: 1 addition & 4 deletions ios/MattermostShare/Extensions/Int64.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ extension Int64 {
let i = floor(log(size) / log(k))

// Format number with thousands separator and everything below 1 giga with no decimal places.
let numberFormatter = NumberFormatter()
numberFormatter.maximumFractionDigits = i < 3 ? 0 : 1
numberFormatter.numberStyle = .decimal

let numberFormatter = i < 3 ? NumberFormatter.noFractionDigitsDecimalFormatter : NumberFormatter.oneFractionDigitDecimalFormatter
let numberString = numberFormatter.string(from: NSNumber(value: size / pow(k, i))) ?? "Unknown"
let suffix = suffixes[Int(i)]
return "\(numberString) \(suffix)"
Expand Down
25 changes: 25 additions & 0 deletions ios/MattermostShare/Extensions/NumberFormatter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// NumberFormatter.swift
// MattermostShare
//
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
//

import Foundation

extension NumberFormatter {
static let noFractionDigitsDecimalFormatter: NumberFormatter = {
let numberFormatter = NumberFormatter()
numberFormatter.maximumFractionDigits = 0
numberFormatter.numberStyle = .decimal
return numberFormatter
}()

static let oneFractionDigitDecimalFormatter: NumberFormatter = {
let numberFormatter = NumberFormatter()
numberFormatter.maximumFractionDigits = 1
numberFormatter.numberStyle = .decimal
return numberFormatter
}()
}
2 changes: 2 additions & 0 deletions ios/MattermostShare/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,7 @@
<string>$(SENTRY_DSN_IOS)</string>
<key>SENTRY_ENABLED</key>
<string>$(SENTRY_ENABLED)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.</string>
</dict>
</plist>
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,30 @@ struct AttachmentsView: View {
var error: String? {
if let server = shareViewModel.server {
if server.uploadsDisabled {
return "File uploads are disabled for the selected server"
return NSLocalizedString("share_extension.upload_disabled",
value: "File uploads are disabled for the selected server",
comment: ""
)
}
let sizeError = attachments.contains { $0.sizeError(server: server)}
let resolutionError = attachments.contains { $0.resolutionError(server: server)}
if sizeError && attachments.count == 1 {
return "File must be less than \(server.maxFileSize.formattedFileSize)"
return NSLocalizedString("share_extension.file_limit.single",
value: "File must be less than {size}",
comment: ""
)
.replacingOccurrences(of: "{size}", with: server.maxFileSize.formattedFileSize)
} else if sizeError {
return "Each file must be less than \(server.maxFileSize.formattedFileSize)"
return NSLocalizedString("share_extension.file_limit.multiple",
value: "Each file must be less than {size}",
comment: ""
)
.replacingOccurrences(of: "{size}", with: server.maxFileSize.formattedFileSize)
} else if resolutionError {
return "Image exceeds maximum dimensions of 7680 x 4320 px"
return NSLocalizedString("share_extension.max_resolution",
value: "Image exceeds maximum dimensions of 7680 x 4320 px",
comment: ""
)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,16 @@ struct MultipleAttachmentView: View {
}

if (attachments.count > 1) {
Text("\(attachments.count) attachments")
.foregroundColor(Color.theme.centerChannelColor.opacity(0.64))
.font(Font.custom("OpenSans", size: 12))
.padding(.leading, 20)
Text(
NSLocalizedString("share_extension.multiple_label",
value: "{count, number} attachments",
comment: ""
)
.replacingOccurrences(of: "{count, number}", with: "\(attachments.count)")
)
.foregroundColor(Color.theme.centerChannelColor.opacity(0.64))
.font(Font.custom("OpenSans", size: 12))
.padding(.leading, 20)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ struct ChannelListView: View {
SearchBarView()
if shareViewModel.search.isEmpty {
HStack {
Text("RECENT")
.font(Font.custom("OpenSans-SemiBold", size: 12))
.foregroundColor(Color.theme.centerChannelColor.opacity(0.64))
Text(
NSLocalizedString("mobile.channel_list.recent", value: "Recent", comment: "")
.uppercased()
)
.font(Font.custom("OpenSans-SemiBold", size: 12))
.foregroundColor(Color.theme.centerChannelColor.opacity(0.64))
Spacer()
}
.padding(.top, 20)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ struct SearchBarView: View {
HStack {
TextField("", text: $shareViewModel.search)
.placeholder(when: shareViewModel.search.isEmpty) {
Text("Find channels...")
.foregroundColor(Color.theme.centerChannelColor.opacity(0.64))
Text(
NSLocalizedString("channel_list.find_channels", value: "Find channels...", comment: "")
)
.foregroundColor(Color.theme.centerChannelColor.opacity(0.64))
}
.padding(.leading, 40)
.padding(.trailing, 30)
Expand Down Expand Up @@ -59,9 +61,11 @@ struct SearchBarView: View {

if isEditing {
Button(action: dismissKeyboard) {
Text("Cancel")
.foregroundColor(Color.theme.centerChannelColor)
.font(Font.custom("OpenSans", size: 14))
Text(
NSLocalizedString("mobile.post.cancel", value: "Cancel", comment: "")
)
.foregroundColor(Color.theme.centerChannelColor)
.font(Font.custom("OpenSans", size: 14))
}
.transition(.move(edge: .trailing))
.animation(.linear(duration: 0.15))
Expand Down
18 changes: 12 additions & 6 deletions ios/MattermostShare/Views/ContentViews/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ struct ContentView: View {
VStack (spacing: 0) {
if shareViewModel.allServers.count > 1 {
OptionView(
navigationTitle: "Select server",
label: "Server",
navigationTitle: NSLocalizedString("share_extension.servers_screen.title", value: "Select server", comment: ""),
label: NSLocalizedString("share_extension.server_label", value: "Server", comment: ""),
value: shareViewModel.server!.displayName
) {
ServerListView()
Expand All @@ -51,8 +51,8 @@ struct ContentView: View {
}
if hasChannels {
OptionView(
navigationTitle: "Select channel",
label: "Channel",
navigationTitle: NSLocalizedString("share_extension.channels_screen.title", value: "Select channel", comment: ""),
label: NSLocalizedString("share_extension.channel_label", value: "Channel", comment: ""),
value: "\(shareViewModel.channel!.displayName) \(shareViewModel.channel!.formattedTeamName)"
) {
ChannelListView()
Expand All @@ -66,10 +66,16 @@ struct ContentView: View {
.padding(.bottom, 10)

if hasChannels {
FloatingTextField(placeholderText: "Enter a message (optional)", text: $message)
FloatingTextField(
placeholderText: NSLocalizedString("share_extension.message", value: "Enter a message (optional)", comment: ""),
text: $message
)
} else {
ErrorLabelView(
error: "You are not a member of a team on the selected server. Select another server or open Mattermost to join a team."
error: NSLocalizedString("share_extension.channel_error",
value: "You are not a member of a team on the selected server. Select another server or open Mattermost to join a team.",
comment: ""
)
)
}

Expand Down
11 changes: 7 additions & 4 deletions ios/MattermostShare/Views/ContentViews/FloatingTextField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,7 @@ struct FloatingTextField: View {
}

func formatLength(_ value: Int64) -> String {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 0
let formatter = NumberFormatter.noFractionDigitsDecimalFormatter
let number = NSNumber(value: value)
return formatter.string(from: number)!
}
Expand All @@ -64,7 +62,12 @@ struct FloatingTextField: View {
VStack (alignment: .leading) {
if (error) {
ErrorLabelView(
error: "Message must be less than \(formatLength(shareViewModel.server!.maxMessageLength)) characters"
error: NSLocalizedString("mobile.message_length.message",
value: "Your current message is too long. Current character count: {count}/{max}",
comment: ""
)
.replacingOccurrences(of: "{count}", with: formatLength(Int64(text.count)))
.replacingOccurrences(of: "{max}", with: formatLength(shareViewModel.server!.maxMessageLength))
)
}
ZStack(alignment: .topLeading) {
Expand Down
41 changes: 30 additions & 11 deletions ios/MattermostShare/Views/ErrorViews/ErrorSharingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,40 @@ struct ErrorSharingView: View {
NotificationCenter.default.post(name: Notification.Name("submit"), object: nil, userInfo: nil)
}
} else {
Text("An error ocurred")
.font(Font.custom("Metropolis-SemiBold", size: 20))
.foregroundColor(Color.theme.centerChannelColor)
Text("There was an error when attempting to share the content to Mattermost.")
.font(Font.custom("OpenSans", size: 16))
Text(
NSLocalizedString("share_extension.error_screen.label", value: "An error ocurred", comment: "")
)
.font(Font.custom("Metropolis-SemiBold", size: 20))
.foregroundColor(Color.theme.centerChannelColor)
Text(
NSLocalizedString("share_extension.error_screen.description",
value: "There was an error when attempting to share the content to {applicationName}.",
comment: ""
)
.replacingOccurrences(
of: "{applicationName}",
with: Bundle.main.infoDictionary?["CFBundleDisplayName"] as? String ?? "Mattermost Beta"
)
)
.font(Font.custom("OpenSans", size: 16))
.foregroundColor(Color.theme.centerChannelColor.opacity(0.72))
Text("Reason: \(error)")
.font(Font.custom("OpenSans", size: 12))
.foregroundColor(Color.theme.centerChannelColor.opacity(0.60))
Text(
NSLocalizedString("share_extension.error_screen.reason",
value: "Reason: {reason}",
comment: ""
)
.replacingOccurrences(of: "{reason}", with: error)
)
.font(Font.custom("OpenSans", size: 12))
.foregroundColor(Color.theme.centerChannelColor.opacity(0.60))
Button {
retrying = true
} label: {
Text("Try again")
.font(Font.custom("OpenSans", size: 16))
.foregroundColor(Color.theme.buttonColor)
Text(
NSLocalizedString("mobile.post.failed_retry", value: "Try again", comment: "")
)
.font(Font.custom("OpenSans", size: 16))
.foregroundColor(Color.theme.buttonColor)
}
.buttonStyle(.borderedProminent)
.tint(Color.theme.buttonBg)
Expand Down
22 changes: 16 additions & 6 deletions ios/MattermostShare/Views/ErrorViews/NoMembershipView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,22 @@ import SwiftUI
struct NoMembershipView: View {
var body: some View {
VStack (spacing: 8) {
Text("Not a member of any team yet")
.font(Font.custom("Metropolis-SemiBold", size: 20))
.foregroundColor(Color.theme.centerChannelColor)
Text("To share content, you'll need to be a member of a team on a Mattermost server.")
.font(Font.custom("OpenSans", size: 16))
.foregroundColor(Color.theme.centerChannelColor.opacity(0.72))
Text(
NSLocalizedString("extension.no_memberships.title",
value: "Not a member of any team yet",
comment: ""
)
)
.font(Font.custom("Metropolis-SemiBold", size: 20))
.foregroundColor(Color.theme.centerChannelColor)
Text(
NSLocalizedString("extension.no_memberships.description",
value: "To share content, you'll need to be a member of a team on a Mattermost server.",
comment: ""
)
)
.font(Font.custom("OpenSans", size: 16))
.foregroundColor(Color.theme.centerChannelColor.opacity(0.72))
}
.padding(.horizontal, 12)
}
Expand Down
Loading

0 comments on commit cc2728a

Please sign in to comment.