Add Tabs customization on iOS

This commit is contained in:
Thomas Ricouard 2023-12-28 11:26:00 +01:00
parent b0ba6c15da
commit 5c2148104c
7 changed files with 976 additions and 5 deletions

View file

@ -14,6 +14,7 @@
069709AA298C9AD7006E4CB5 /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 069709A9298C9AD7006E4CB5 /* AboutView.swift */; };
639CDF9C296AC82F00C35E58 /* SafariRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 639CDF9B296AC82F00C35E58 /* SafariRouter.swift */; };
9F15D6002B3D6A850008C220 /* NavigationTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F15D5FF2B3D6A850008C220 /* NavigationTab.swift */; };
9F15D6022B3D6E280008C220 /* TabbarEntriesSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F15D6012B3D6E280008C220 /* TabbarEntriesSettingsView.swift */; };
9F18801229AE477F00D85459 /* tabSelection.wav in Resources */ = {isa = PBXBuildFile; fileRef = 9F18800A29AE477E00D85459 /* tabSelection.wav */; };
9F18801329AE477F00D85459 /* share.wav in Resources */ = {isa = PBXBuildFile; fileRef = 9F18800B29AE477E00D85459 /* share.wav */; };
9F18801429AE477F00D85459 /* bookmark.wav in Resources */ = {isa = PBXBuildFile; fileRef = 9F18800C29AE477E00D85459 /* bookmark.wav */; };
@ -162,6 +163,7 @@
8C27D979298471E900CDF593 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/InfoPlist.strings; sourceTree = "<group>"; };
9664F1A8299BA5F700CBE70E /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
9F15D5FF2B3D6A850008C220 /* NavigationTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationTab.swift; sourceTree = "<group>"; };
9F15D6012B3D6E280008C220 /* TabbarEntriesSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabbarEntriesSettingsView.swift; sourceTree = "<group>"; };
9F18800A29AE477E00D85459 /* tabSelection.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = tabSelection.wav; sourceTree = "<group>"; };
9F18800B29AE477E00D85459 /* share.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = share.wav; sourceTree = "<group>"; };
9F18800C29AE477E00D85459 /* bookmark.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = bookmark.wav; sourceTree = "<group>"; };
@ -522,6 +524,7 @@
9F2A540629699698009B2D7C /* SupportAppView.swift */,
D08A9C3429956CFA00204A4A /* SwipeActionsSettingsView.swift */,
9FA6FD6129C04A8800E2312C /* TranslationSettingsView.swift */,
9F15D6012B3D6E280008C220 /* TabbarEntriesSettingsView.swift */,
);
path = Settings;
sourceTree = "<group>";
@ -826,6 +829,7 @@
9F35DB4C2952005C00B3281A /* MessagesTab.swift in Sources */,
9FAD85CF2975B68900496AB1 /* SideBarView.swift in Sources */,
9FAE4ACB293783B000772766 /* SettingsTab.swift in Sources */,
9F15D6022B3D6E280008C220 /* TabbarEntriesSettingsView.swift in Sources */,
9F7335F92968576500AFF0BA /* DisplaySettingsView.swift in Sources */,
9F2A540729699698009B2D7C /* SupportAppView.swift in Sources */,
9FB183292AE9449100BBB692 /* IceCubesApp+Scene.swift in Sources */,

View file

@ -30,11 +30,15 @@ struct IceCubesApp: App {
@State var selectedTab: Tab = .timeline
@State var popToRootTab: Tab = .other
@State var iosTabs = iOSTabs.shared
@State var sideBarLoadedTabs: Set<Tab> = Set()
@State var isSupporter: Bool = false
var availableTabs: [Tab] {
appAccountsManager.currentClient.isAuth ? Tab.loggedInTabs() : Tab.loggedOutTab()
if UIDevice.current.userInterfaceIdiom == .phone {
return appAccountsManager.currentClient.isAuth ? iosTabs.tabs : Tab.loggedOutTab()
}
return appAccountsManager.currentClient.isAuth ? Tab.loggedInTabs() : Tab.loggedOutTab()
}
var body: some Scene {

View file

@ -1,8 +1,17 @@
import SwiftUI
import Env
import AppAccount
import DesignSystem
@MainActor
struct NavigationTab<Content: View>: View {
@Environment(\.isSecondaryColumn) private var isSecondaryColumn: Bool
@Environment(AppAccountsManager.self) private var appAccount
@Environment(CurrentAccount.self) private var currentAccount
@Environment(UserPreferences.self) private var userPreferences
@Environment(Theme.self) private var theme
var content: () -> Content
@State private var routerPath = RouterPath()
@ -16,7 +25,25 @@ struct NavigationTab<Content: View>: View {
content()
.withEnvironments()
.withAppRouter()
.withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
.toolbar {
if !isSecondaryColumn {
statusEditorToolbarItem(routerPath: routerPath,
visibility: userPreferences.postVisibility)
if UIDevice.current.userInterfaceIdiom != .pad {
ToolbarItem(placement: .navigationBarLeading) {
AppAccountsSelectorView(routerPath: routerPath)
}
}
}
if UIDevice.current.userInterfaceIdiom == .pad {
if (!isSecondaryColumn && !userPreferences.showiPadSecondaryColumn) || isSecondaryColumn {
SecondaryColumnToolbarItem()
}
}
}
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .navigationBar)
}
.environment(routerPath)
}
}
}

View file

@ -160,6 +160,11 @@ struct SettingsTabs: View {
NavigationLink(destination: SwipeActionsSettingsView()) {
Label("settings.general.swipeactions", systemImage: "hand.draw")
}
if UIDevice.current.userInterfaceIdiom == .phone {
NavigationLink(destination: TabbarEntriesSettingsView()) {
Label("settings.general.tabbarEntries", systemImage: "platter.filled.bottom.iphone")
}
}
NavigationLink(destination: TranslationSettingsView()) {
Label("settings.general.translate", systemImage: "captions.bubble")
}

View file

@ -0,0 +1,51 @@
import DesignSystem
import Env
import SwiftUI
@MainActor
struct TabbarEntriesSettingsView: View {
@Environment(Theme.self) private var theme
@Environment(UserPreferences.self) private var userPreferences
@State private var tabs = iOSTabs.shared
var body: some View {
Form {
Section {
Picker("settings.tabs.first-tab", selection: $tabs.firstTab) {
ForEach(Tab.allCases) { tab in
tab.label.tag(tab)
}
}
Picker("settings.tabs.second-tab", selection: $tabs.secondTab) {
ForEach(Tab.allCases) { tab in
tab.label.tag(tab)
}
}
Picker("settings.tabs.third-tab", selection: $tabs.thirdTab) {
ForEach(Tab.allCases) { tab in
tab.label.tag(tab)
}
}
Picker("settings.tabs.fourth-tab", selection: $tabs.fourthTab) {
ForEach(Tab.allCases) { tab in
tab.label.tag(tab)
}
}
Picker("settings.tabs.fifth-tab", selection: $tabs.fifthTab) {
ForEach(Tab.allCases) { tab in
tab.label.tag(tab)
}
}
}
#if !os(visionOS)
.listRowBackground(theme.primaryBackgroundColor)
#endif
}
.navigationTitle("settings.general.tabbarEntries")
#if !os(visionOS)
.scrollContentBackground(.hidden)
.background(theme.secondaryBackgroundColor)
#endif
}
}

View file

@ -6,7 +6,7 @@ import Status
import SwiftUI
@MainActor
enum Tab: Int, Identifiable, Hashable {
enum Tab: Int, Identifiable, Hashable, CaseIterable {
case timeline, notifications, mentions, explore, messages, settings, other
case trending, federated, local
case profile
@ -82,7 +82,7 @@ enum Tab: Int, Identifiable, Hashable {
case .notifications:
Label("tab.notifications", systemImage: iconName)
case .mentions:
Label("tab.notifications", systemImage: iconName)
Label("tab.mentions", systemImage: iconName)
case .explore:
Label("tab.explore", systemImage: iconName)
case .messages:
@ -131,3 +131,63 @@ enum Tab: Int, Identifiable, Hashable {
}
}
}
@Observable
class iOSTabs {
enum TabEntries: String {
case first, second, third, fourth, fifth
}
class Storage {
@AppStorage(TabEntries.first.rawValue) var firstTab = Tab.timeline
@AppStorage(TabEntries.second.rawValue) var secondTab = Tab.notifications
@AppStorage(TabEntries.third.rawValue) var thirdTab = Tab.explore
@AppStorage(TabEntries.fourth.rawValue) var fourthTab = Tab.messages
@AppStorage(TabEntries.fifth.rawValue) var fifthTab = Tab.profile
}
private let storage = Storage()
public static let shared = iOSTabs()
var tabs: [Tab] {
[firstTab, secondTab, thirdTab, fourthTab, fifthTab]
}
var firstTab: Tab {
didSet {
storage.firstTab = firstTab
}
}
var secondTab: Tab {
didSet {
storage.secondTab = secondTab
}
}
var thirdTab: Tab {
didSet {
storage.thirdTab = thirdTab
}
}
var fourthTab: Tab {
didSet {
storage.fourthTab = fourthTab
}
}
var fifthTab: Tab {
didSet {
storage.fifthTab = fifthTab
}
}
private init() {
firstTab = storage.firstTab
secondTab = storage.secondTab
thirdTab = storage.thirdTab
fourthTab = storage.fourthTab
fifthTab = storage.fifthTab
}
}

View file

@ -46977,6 +46977,124 @@
}
}
},
"settings.general.tabbarEntries" : {
"localizations" : {
"be" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tabs Customizations"
}
},
"ca" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tabs Customizations"
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tabs Customizations"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tabs Customizations"
}
},
"en-GB" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tabs Customizations"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tabs Customizations"
}
},
"eu" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tabs Customizations"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tabs Customizations"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tabs Customizations"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tabs Customizations"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tabs Customizations"
}
},
"nb" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tabs Customizations"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tabs Customizations"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tabs Customizations"
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tabs Customizations"
}
},
"tr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tabs Customizations"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tabs Customizations"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Tabs Customizations"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Tabs Customizations"
}
}
}
},
"settings.general.translate" : {
"localizations" : {
"be" : {
@ -55243,6 +55361,590 @@
}
}
},
"settings.tabs.fifth-tab" : {
"localizations" : {
"be" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fifth Tab"
}
},
"ca" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fifth Tab"
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fifth Tab"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fifth Tab"
}
},
"en-GB" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fifth Tab"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fifth Tab"
}
},
"eu" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fifth Tab"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fifth Tab"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fifth Tab"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fifth Tab"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fifth Tab"
}
},
"nb" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fifth Tab"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fifth Tab"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fifth Tab"
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fifth Tab"
}
},
"tr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fifth Tab"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fifth Tab"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Fifth Tab"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Fifth Tab"
}
}
}
},
"settings.tabs.first-tab" : {
"localizations" : {
"be" : {
"stringUnit" : {
"state" : "translated",
"value" : "First Tab"
}
},
"ca" : {
"stringUnit" : {
"state" : "translated",
"value" : "First Tab"
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "First Tab"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "First Tab"
}
},
"en-GB" : {
"stringUnit" : {
"state" : "translated",
"value" : "First Tab"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "First Tab"
}
},
"eu" : {
"stringUnit" : {
"state" : "translated",
"value" : "First Tab"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "First Tab"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "First Tab"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "First Tab"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "First Tab"
}
},
"nb" : {
"stringUnit" : {
"state" : "translated",
"value" : "First Tab"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "First Tab"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "First Tab"
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "First Tab"
}
},
"tr" : {
"stringUnit" : {
"state" : "translated",
"value" : "First Tab"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "First Tab"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "First Tab"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "First Tab"
}
}
}
},
"settings.tabs.fourth-tab" : {
"localizations" : {
"be" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fourth Tab"
}
},
"ca" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fourth Tab"
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fourth Tab"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fourth Tab"
}
},
"en-GB" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fourth Tab"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fourth Tab"
}
},
"eu" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fourth Tab"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fourth Tab"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fourth Tab"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fourth Tab"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fourth Tab"
}
},
"nb" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fourth Tab"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fourth Tab"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fourth Tab"
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fourth Tab"
}
},
"tr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fourth Tab"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fourth Tab"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Fourth Tab"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Fourth Tab"
}
}
}
},
"settings.tabs.second-tab" : {
"localizations" : {
"be" : {
"stringUnit" : {
"state" : "translated",
"value" : "Second Tab"
}
},
"ca" : {
"stringUnit" : {
"state" : "translated",
"value" : "Second Tab"
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Second Tab"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Second Tab"
}
},
"en-GB" : {
"stringUnit" : {
"state" : "translated",
"value" : "Second Tab"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Second Tab"
}
},
"eu" : {
"stringUnit" : {
"state" : "translated",
"value" : "Second Tab"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Second Tab"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "Second Tab"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "Second Tab"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "Second Tab"
}
},
"nb" : {
"stringUnit" : {
"state" : "translated",
"value" : "Second Tab"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Second Tab"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Second Tab"
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Second Tab"
}
},
"tr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Second Tab"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Second Tab"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Second Tab"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Second Tab"
}
}
}
},
"settings.tabs.third-tab" : {
"localizations" : {
"be" : {
"stringUnit" : {
"state" : "translated",
"value" : "Third Tab"
}
},
"ca" : {
"stringUnit" : {
"state" : "translated",
"value" : "Third Tab"
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Third Tab"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Third Tab"
}
},
"en-GB" : {
"stringUnit" : {
"state" : "translated",
"value" : "Third Tab"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Third Tab"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Third Tab"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "Third Tab"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "Third Tab"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "Third Tab"
}
},
"nb" : {
"stringUnit" : {
"state" : "translated",
"value" : "Third Tab"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Third Tab"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Third Tab"
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Third Tab"
}
},
"tr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Third Tab"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Third Tab"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Third Tab"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Third Tab"
}
}
}
},
"settings.timeline.add" : {
"localizations" : {
"be" : {
@ -69208,6 +69910,124 @@
}
}
},
"tab.mentions" : {
"localizations" : {
"be" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mentions"
}
},
"ca" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mentions"
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mentions"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mentions"
}
},
"en-GB" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mentions"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mentions"
}
},
"eu" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mentions"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mentions"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mentions"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mentions"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mentions"
}
},
"nb" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mentions"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mentions"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mentions"
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mentions"
}
},
"tr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mentions"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mentions"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Mentions"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Mentions"
}
}
}
},
"tab.messages" : {
"localizations" : {
"be" : {