@mwater/visualization 5.4.1 → 5.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (273) hide show
  1. package/lib/ColorComponent.js +2 -1
  2. package/lib/IdSelection.d.ts +16 -0
  3. package/lib/IdSelection.js +59 -0
  4. package/lib/MWaterAddRelatedIndicatorComponent.js +2 -2
  5. package/lib/MWaterCompleteTableSelectComponent.d.ts +3 -8
  6. package/lib/MWaterCompleteTableSelectComponent.js +36 -42
  7. package/lib/MWaterLoaderComponent.d.ts +11 -10
  8. package/lib/MWaterLoaderComponent.js +1 -1
  9. package/lib/MWaterResponsesFilterComponent.js +1 -1
  10. package/lib/MWaterTableSelectComponent.d.ts +0 -1
  11. package/lib/MWaterTableSelectComponent.js +4 -6
  12. package/lib/autotranslate.d.ts +20 -0
  13. package/lib/autotranslate.js +122 -0
  14. package/lib/axes/AxisBuilder.js +3 -3
  15. package/lib/axes/AxisColorEditorComponent.js +4 -0
  16. package/lib/axes/AxisComponent.d.ts +8 -12
  17. package/lib/axes/AxisComponent.js +32 -80
  18. package/lib/axes/CategoryMapComponent.js +4 -4
  19. package/lib/axes/RangesComponent.js +2 -2
  20. package/lib/dashboards/DashboardComponent.d.ts +12 -20
  21. package/lib/dashboards/DashboardComponent.js +109 -69
  22. package/lib/dashboards/DashboardDesign.d.ts +11 -2
  23. package/lib/dashboards/DashboardUtils.d.ts +5 -0
  24. package/lib/dashboards/DashboardUtils.js +30 -0
  25. package/lib/dashboards/DashboardViewComponent.d.ts +2 -0
  26. package/lib/dashboards/DashboardViewComponent.js +16 -3
  27. package/lib/dashboards/ServerDashboardDataSource.js +2 -1
  28. package/lib/dashboards/SettingsModalComponent.d.ts +1 -1
  29. package/lib/dashboards/SettingsModalComponent.js +256 -19
  30. package/lib/dashboards/WidgetComponent.d.ts +6 -3
  31. package/lib/dashboards/WidgetComponent.js +3 -1
  32. package/lib/datagrids/CellEditor.d.ts +19 -0
  33. package/lib/datagrids/CellEditor.js +223 -0
  34. package/lib/datagrids/DatagridComponent.d.ts +18 -87
  35. package/lib/datagrids/DatagridComponent.js +304 -222
  36. package/lib/datagrids/DatagridViewComponent.d.ts +15 -53
  37. package/lib/datagrids/DatagridViewComponent.js +256 -257
  38. package/lib/datagrids/DirectDatagridDataSource.js +2 -3
  39. package/lib/datagrids/ExprCellComponent.d.ts +8 -15
  40. package/lib/datagrids/ExprCellComponent.js +11 -15
  41. package/lib/datagrids/FindReplaceModalComponent.d.ts +4 -6
  42. package/lib/datagrids/FindReplaceModalComponent.js +38 -75
  43. package/lib/index.css +1 -1
  44. package/lib/index.d.ts +0 -1
  45. package/lib/index.js +0 -1
  46. package/lib/languages.js +6 -1
  47. package/lib/layouts/blocks/HorizontalBlockComponent.js +2 -2
  48. package/lib/mWaterLoader.d.ts +1 -1
  49. package/lib/maps/BufferLayer.d.ts +7 -5
  50. package/lib/maps/BufferLayer.js +69 -48
  51. package/lib/maps/BufferLayerDesign.d.ts +21 -14
  52. package/lib/maps/BufferLayerDesignerComponent.d.ts +16 -31
  53. package/lib/maps/BufferLayerDesignerComponent.js +68 -102
  54. package/lib/maps/ChoroplethLayer.d.ts +5 -4
  55. package/lib/maps/ChoroplethLayer.js +32 -9
  56. package/lib/maps/ChoroplethLayerDesign.d.ts +6 -2
  57. package/lib/maps/ChoroplethLayerDesigner.js +4 -2
  58. package/lib/maps/ClusterLayer.d.ts +3 -4
  59. package/lib/maps/ClusterLayer.js +2 -1
  60. package/lib/maps/DetailLevelSelectComponent.js +1 -1
  61. package/lib/maps/DirectMapDataSource.js +2 -1
  62. package/lib/maps/EditPopupComponent.js +5 -3
  63. package/lib/maps/GridLayer.d.ts +3 -4
  64. package/lib/maps/GridLayer.js +2 -1
  65. package/lib/maps/GridLayerDesigner.js +5 -3
  66. package/lib/maps/HoverContent.d.ts +11 -3
  67. package/lib/maps/HoverContent.js +25 -9
  68. package/lib/maps/Layer.d.ts +24 -3
  69. package/lib/maps/Layer.js +5 -1
  70. package/lib/maps/LayerFactory.js +0 -8
  71. package/lib/maps/LayerLegendComponent.js +0 -1
  72. package/lib/maps/LayerSwitcherComponent.d.ts +1 -0
  73. package/lib/maps/LayerSwitcherComponent.js +1 -1
  74. package/lib/maps/LeafletMapComponent.js +3 -1
  75. package/lib/maps/LegendComponent.d.ts +1 -0
  76. package/lib/maps/LegendComponent.js +9 -1
  77. package/lib/maps/MWaterServerLayer.d.ts +2 -2
  78. package/lib/maps/MWaterServerLayer.js +2 -2
  79. package/lib/maps/MapComponent.js +3 -3
  80. package/lib/maps/MapDesign.d.ts +2 -0
  81. package/lib/maps/MapDesignerComponent.d.ts +4 -3
  82. package/lib/maps/MapDesignerComponent.js +68 -74
  83. package/lib/maps/MapLayerViewDesignerComponent.js +2 -2
  84. package/lib/maps/MapUtils.d.ts +4 -0
  85. package/lib/maps/MapUtils.js +19 -0
  86. package/lib/maps/MapViewComponent.d.ts +8 -3
  87. package/lib/maps/MarkersLayer.d.ts +5 -4
  88. package/lib/maps/MarkersLayer.js +33 -7
  89. package/lib/maps/MarkersLayerDesign.d.ts +19 -16
  90. package/lib/maps/PopupFilterJoinsUtils.d.ts +6 -3
  91. package/lib/maps/PopupFilterJoinsUtils.js +0 -6
  92. package/lib/maps/RasterMapViewComponent.d.ts +3 -31
  93. package/lib/maps/RasterMapViewComponent.js +7 -2
  94. package/lib/maps/ServerMapDataSource.js +2 -1
  95. package/lib/maps/SwitchableTileUrlLayer.d.ts +3 -3
  96. package/lib/maps/SwitchableTileUrlLayer.js +2 -1
  97. package/lib/maps/TileUrlLayer.d.ts +4 -5
  98. package/lib/maps/TileUrlLayer.js +2 -1
  99. package/lib/maps/VectorMapViewComponent.d.ts +5 -37
  100. package/lib/maps/VectorMapViewComponent.js +19 -8
  101. package/lib/maps/maps.d.ts +3 -0
  102. package/lib/quickfilter/Quickfilter.d.ts +2 -0
  103. package/lib/quickfilter/QuickfiltersComponent.d.ts +2 -0
  104. package/lib/quickfilter/QuickfiltersComponent.js +9 -7
  105. package/lib/quickfilter/QuickfiltersDesignComponent.d.ts +5 -30
  106. package/lib/quickfilter/QuickfiltersDesignComponent.js +56 -63
  107. package/lib/richtext/ExprItemsHtmlConverter.d.ts +5 -2
  108. package/lib/richtext/ExprItemsHtmlConverter.js +4 -4
  109. package/lib/richtext/ExprItemsTranslator.d.ts +5 -0
  110. package/lib/richtext/ExprItemsTranslator.js +149 -0
  111. package/lib/richtext/ItemsHtmlConverter.d.ts +1 -1
  112. package/lib/richtext/ItemsHtmlConverter.js +31 -15
  113. package/lib/wellknown.js +12 -9
  114. package/lib/widgets/IFrameWidget.d.ts +4 -4
  115. package/lib/widgets/ImageWidget.d.ts +7 -4
  116. package/lib/widgets/ImageWidget.js +9 -1
  117. package/lib/widgets/ImageWidgetComponent.d.ts +1 -0
  118. package/lib/widgets/ImageWidgetComponent.js +1 -1
  119. package/lib/widgets/MapWidget.d.ts +5 -48
  120. package/lib/widgets/MapWidget.js +26 -63
  121. package/lib/widgets/MarkdownWidget.d.ts +3 -0
  122. package/lib/widgets/MarkdownWidget.js +3 -0
  123. package/lib/widgets/TOCWidget.d.ts +15 -27
  124. package/lib/widgets/TOCWidget.js +107 -183
  125. package/lib/widgets/Widget.d.ts +18 -7
  126. package/lib/widgets/Widget.js +4 -0
  127. package/lib/widgets/WidgetScopesViewComponent.js +1 -1
  128. package/lib/widgets/charts/Chart.d.ts +10 -1
  129. package/lib/widgets/charts/Chart.js +22 -11
  130. package/lib/widgets/charts/ChartViewComponent.d.ts +4 -0
  131. package/lib/widgets/charts/ChartViewComponent.js +6 -3
  132. package/lib/widgets/charts/ChartWidget.d.ts +2 -0
  133. package/lib/widgets/charts/ChartWidget.js +9 -1
  134. package/lib/widgets/charts/ChartWidgetComponent.d.ts +4 -0
  135. package/lib/widgets/charts/ChartWidgetComponent.js +2 -2
  136. package/lib/widgets/charts/calendar/CalendarChart.d.ts +1 -0
  137. package/lib/widgets/charts/calendar/CalendarChart.js +26 -0
  138. package/lib/widgets/charts/calendar/CalendarChartViewComponent.js +3 -1
  139. package/lib/widgets/charts/imagemosaic/ImageMosaicChart.d.ts +1 -0
  140. package/lib/widgets/charts/imagemosaic/ImageMosaicChart.js +8 -0
  141. package/lib/widgets/charts/layered/LayeredChart.d.ts +2 -0
  142. package/lib/widgets/charts/layered/LayeredChart.js +63 -3
  143. package/lib/widgets/charts/layered/LayeredChartCompiler.d.ts +1 -1
  144. package/lib/widgets/charts/layered/LayeredChartCompiler.js +1 -1
  145. package/lib/widgets/charts/layered/LayeredChartDesignerComponent.js +2 -2
  146. package/lib/widgets/charts/layered/LayeredChartViewComponent.js +8 -3
  147. package/lib/widgets/charts/pivot/PivotChart.d.ts +1 -0
  148. package/lib/widgets/charts/pivot/PivotChart.js +63 -0
  149. package/lib/widgets/charts/pivot/PivotChartLayoutComponent.js +1 -1
  150. package/lib/widgets/charts/pivot/SegmentDesignerComponent.js +7 -4
  151. package/lib/widgets/charts/table/OrderingsComponent.js +1 -1
  152. package/lib/widgets/charts/table/TableChart.d.ts +1 -0
  153. package/lib/widgets/charts/table/TableChart.js +15 -0
  154. package/lib/widgets/text/TextComponent.d.ts +11 -4
  155. package/lib/widgets/text/TextComponent.js +11 -8
  156. package/lib/widgets/text/TextWidget.d.ts +6 -3
  157. package/lib/widgets/text/TextWidget.js +7 -1
  158. package/lib/widgets/text/TextWidgetComponent.d.ts +4 -0
  159. package/lib/widgets/text/TextWidgetComponent.js +7 -1
  160. package/lib/widgets/text/TextWidgetDesign.d.ts +2 -4
  161. package/lib/widgets/text/TextWidgetDesign.js +1 -1
  162. package/package.json +7 -8
  163. package/src/ColorComponent.tsx +1 -2
  164. package/src/IdSelection.ts +62 -0
  165. package/src/MWaterAddRelatedIndicatorComponent.ts +3 -2
  166. package/src/MWaterCompleteTableSelectComponent.tsx +36 -46
  167. package/src/MWaterLoaderComponent.ts +28 -26
  168. package/src/MWaterResponsesFilterComponent.ts +5 -2
  169. package/src/MWaterTableSelectComponent.tsx +5 -9
  170. package/src/autotranslate.ts +141 -0
  171. package/src/axes/AxisBuilder.ts +3 -3
  172. package/src/axes/AxisColorEditorComponent.tsx +5 -0
  173. package/src/axes/{AxisComponent.ts → AxisComponent.tsx} +106 -106
  174. package/src/axes/CategoryMapComponent.ts +4 -4
  175. package/src/axes/RangesComponent.ts +3 -2
  176. package/src/dashboards/DashboardComponent.tsx +189 -125
  177. package/src/dashboards/DashboardDesign.ts +9 -2
  178. package/src/dashboards/DashboardUtils.ts +39 -0
  179. package/src/dashboards/DashboardViewComponent.tsx +22 -3
  180. package/src/dashboards/ServerDashboardDataSource.ts +2 -1
  181. package/src/dashboards/SettingsModalComponent.tsx +450 -35
  182. package/src/dashboards/WidgetComponent.tsx +12 -6
  183. package/src/datagrids/CellEditor.tsx +354 -0
  184. package/src/datagrids/DatagridComponent.tsx +646 -0
  185. package/src/datagrids/DatagridViewComponent.tsx +539 -0
  186. package/src/datagrids/DirectDatagridDataSource.ts +2 -3
  187. package/src/datagrids/{ExprCellComponent.ts → ExprCellComponent.tsx} +28 -23
  188. package/src/datagrids/{FindReplaceModalComponent.ts → FindReplaceModalComponent.tsx} +109 -122
  189. package/src/index.css +1 -1
  190. package/src/index.ts +0 -1
  191. package/src/languages.ts +6 -1
  192. package/src/layouts/blocks/HorizontalBlockComponent.ts +2 -2
  193. package/src/mWaterLoader.ts +1 -1
  194. package/src/maps/BufferLayer.ts +83 -60
  195. package/src/maps/BufferLayerDesign.ts +20 -14
  196. package/src/maps/BufferLayerDesignerComponent.tsx +309 -0
  197. package/src/maps/ChoroplethLayer.ts +40 -19
  198. package/src/maps/ChoroplethLayerDesign.ts +4 -2
  199. package/src/maps/ChoroplethLayerDesigner.tsx +4 -2
  200. package/src/maps/ClusterLayer.ts +4 -10
  201. package/src/maps/DetailLevelSelectComponent.ts +1 -1
  202. package/src/maps/DirectMapDataSource.ts +2 -1
  203. package/src/maps/EditPopupComponent.ts +7 -3
  204. package/src/maps/GridLayer.ts +4 -10
  205. package/src/maps/GridLayerDesigner.tsx +5 -3
  206. package/src/maps/HoverContent.tsx +40 -16
  207. package/src/maps/Layer.ts +28 -10
  208. package/src/maps/LayerFactory.ts +0 -8
  209. package/src/maps/LayerLegendComponent.ts +2 -4
  210. package/src/maps/LayerSwitcherComponent.tsx +6 -2
  211. package/src/maps/LeafletMapComponent.tsx +3 -1
  212. package/src/maps/LegendComponent.tsx +10 -1
  213. package/src/maps/MWaterServerLayer.ts +3 -3
  214. package/src/maps/MapComponent.ts +3 -3
  215. package/src/maps/MapDesign.ts +3 -0
  216. package/src/maps/MapDesignerComponent.tsx +165 -162
  217. package/src/maps/MapLayerViewDesignerComponent.ts +2 -2
  218. package/src/maps/MapUtils.ts +24 -0
  219. package/src/maps/MapViewComponent.tsx +11 -3
  220. package/src/maps/MarkersLayer.ts +44 -18
  221. package/src/maps/MarkersLayerDesign.ts +19 -16
  222. package/src/maps/PopupFilterJoinsUtils.ts +6 -2
  223. package/src/maps/RasterMapViewComponent.ts +9 -45
  224. package/src/maps/ServerMapDataSource.ts +2 -2
  225. package/src/maps/SwitchableTileUrlLayer.tsx +4 -10
  226. package/src/maps/TileUrlLayer.tsx +4 -10
  227. package/src/maps/VectorMapViewComponent.tsx +28 -55
  228. package/src/maps/maps.ts +3 -0
  229. package/src/quickfilter/Quickfilter.ts +3 -0
  230. package/src/quickfilter/QuickfiltersComponent.ts +13 -7
  231. package/src/quickfilter/QuickfiltersDesignComponent.tsx +127 -128
  232. package/src/richtext/ExprItemsHtmlConverter.ts +9 -5
  233. package/src/richtext/ExprItemsTranslator.ts +176 -0
  234. package/src/richtext/ItemsHtmlConverter.ts +33 -18
  235. package/src/wellknown.ts +33 -30
  236. package/src/widgets/ImageWidget.ts +10 -1
  237. package/src/widgets/ImageWidgetComponent.ts +3 -2
  238. package/src/widgets/{MapWidget.ts → MapWidget.tsx} +90 -101
  239. package/src/widgets/MarkdownWidget.ts +3 -0
  240. package/src/widgets/TOCWidget.tsx +281 -0
  241. package/src/widgets/Widget.ts +25 -5
  242. package/src/widgets/WidgetScopesViewComponent.ts +2 -1
  243. package/src/widgets/charts/Chart.ts +31 -12
  244. package/src/widgets/charts/ChartViewComponent.ts +13 -3
  245. package/src/widgets/charts/ChartWidget.ts +11 -1
  246. package/src/widgets/charts/ChartWidgetComponent.tsx +9 -1
  247. package/src/widgets/charts/calendar/CalendarChart.ts +29 -0
  248. package/src/widgets/charts/calendar/CalendarChartViewComponent.tsx +3 -1
  249. package/src/widgets/charts/imagemosaic/ImageMosaicChart.ts +9 -0
  250. package/src/widgets/charts/layered/LayeredChart.ts +71 -3
  251. package/src/widgets/charts/layered/LayeredChartCompiler.ts +2 -2
  252. package/src/widgets/charts/layered/LayeredChartDesignerComponent.tsx +4 -2
  253. package/src/widgets/charts/layered/LayeredChartViewComponent.ts +10 -4
  254. package/src/widgets/charts/pivot/PivotChart.ts +73 -0
  255. package/src/widgets/charts/pivot/PivotChartLayoutComponent.tsx +1 -1
  256. package/src/widgets/charts/pivot/SegmentDesignerComponent.tsx +6 -4
  257. package/src/widgets/charts/table/OrderingsComponent.tsx +2 -1
  258. package/src/widgets/charts/table/TableChart.ts +17 -0
  259. package/src/widgets/text/TextComponent.tsx +22 -12
  260. package/src/widgets/text/TextWidget.ts +9 -2
  261. package/src/widgets/text/TextWidgetComponent.tsx +16 -1
  262. package/src/widgets/text/TextWidgetDesign.ts +4 -7
  263. package/test/IdSelectionTests.ts +54 -0
  264. package/test/LayeredChartCompilerTests.ts +0 -2
  265. package/test/richtext/ExprItemsTranslatorTests.ts +144 -0
  266. package/test/wellknownTests.ts +144 -0
  267. package/src/datagrids/DatagridComponent.ts +0 -478
  268. package/src/datagrids/DatagridViewComponent.ts +0 -464
  269. package/src/datagrids/EditExprCellComponent.tsx +0 -305
  270. package/src/datagrids/README.md +0 -3
  271. package/src/maps/BufferLayerDesignerComponent.ts +0 -311
  272. package/src/widgets/TOCWidget.ts +0 -326
  273. package/test/LegoLayoutEngineTests.ts +0 -69
@@ -0,0 +1,62 @@
1
+ /** Immutable selection class for selecting ids */
2
+ export default class IdSelection {
3
+ ids: { [id: string]: true }
4
+ inverted: boolean
5
+
6
+ // ids is map of ids to true, inverted is boolean
7
+ constructor(ids = {}, inverted = false) {
8
+ this.ids = ids
9
+ this.inverted = inverted
10
+ }
11
+
12
+ isSelected(id: string) {
13
+ if (this.ids[id]) {
14
+ return !this.inverted
15
+ }
16
+ return this.inverted
17
+ }
18
+
19
+ isNone() {
20
+ return Object.keys(this.ids).length === 0 && !this.inverted
21
+ }
22
+
23
+ all() {
24
+ return new IdSelection({}, true)
25
+ }
26
+
27
+ none() {
28
+ return new IdSelection({}, false)
29
+ }
30
+
31
+ invert() {
32
+ return new IdSelection(this.ids, !this.inverted)
33
+ }
34
+
35
+ add(id: string) {
36
+ if (this.inverted) {
37
+ const newIds = { ...this.ids }
38
+ delete newIds[id]
39
+ return new IdSelection(newIds, true)
40
+ } else {
41
+ return new IdSelection({ ...this.ids, [id]: true }, false)
42
+ }
43
+ }
44
+
45
+ remove(id: string) {
46
+ if (!this.inverted) {
47
+ const newIds = { ...this.ids }
48
+ delete newIds[id]
49
+ return new IdSelection(newIds, false)
50
+ } else {
51
+ return new IdSelection({ ...this.ids, [id]: true }, true)
52
+ }
53
+ }
54
+
55
+ toggle(id: string) {
56
+ if (this.isSelected(id)) {
57
+ return this.remove(id)
58
+ } else {
59
+ return this.add(id)
60
+ }
61
+ }
62
+ }
@@ -124,10 +124,11 @@ export default class MWaterAddRelatedIndicatorComponent extends React.Component<
124
124
  { style: { paddingLeft: 5 }, className: "text-muted" },
125
125
  T`Other Available Indicators. Click to enable. `,
126
126
  R("i", { className: "fa fa-check-circle" }),
127
- T` = recommended`,
127
+ " = ",
128
+ T`recommended`,
128
129
 
129
130
  !this.state.indicators
130
- ? R("div", { className: "text-muted" }, R("i", { className: "fa fa-spin fa-spinner" }), T` Loading...`)
131
+ ? R("div", { className: "text-muted" }, R("i", { className: "fa fa-spin fa-spinner" }), " ", T`Loading...`)
131
132
  : undefined,
132
133
 
133
134
  R(
@@ -12,7 +12,6 @@ import { MWaterCustomTablesetListComponent } from "./MWaterCustomTablesetListCom
12
12
  import { MWaterMetricsTableListComponent } from "./MWaterMetricsTableListComponent"
13
13
  import { Form } from "@mwater/forms"
14
14
  import { MWaterAssetSystemsListComponent } from "./MWaterAssetSystemsListComponent"
15
- import { LocaleContext } from "@mwater/expressions-ui"
16
15
 
17
16
  const sitesOrder: { [table: string]: number } = {
18
17
  "entities.water_point": 1,
@@ -52,8 +51,6 @@ interface MWaterCompleteTableSelectComponentProps {
52
51
  export default class MWaterCompleteTableSelectComponent extends React.Component<MWaterCompleteTableSelectComponentProps, {
53
52
  showLegacyAssets: boolean
54
53
  }> {
55
- static contextType = LocaleContext
56
-
57
54
  constructor(props: MWaterCompleteTableSelectComponentProps) {
58
55
  super(props)
59
56
 
@@ -104,8 +101,8 @@ export default class MWaterCompleteTableSelectComponent extends React.Component<
104
101
  _.map(types, (tableId) => {
105
102
  table = this.props.schema.getTable(tableId)!
106
103
  return {
107
- name: ExprUtils.localizeString(table.name, this.context),
108
- desc: ExprUtils.localizeString(table.desc, this.context),
104
+ name: ExprUtils.localizeString(table.name, T.locale),
105
+ desc: ExprUtils.localizeString(table.desc, T.locale),
109
106
  onClick: this.props.onChange.bind(null, table.id)
110
107
  }
111
108
  })
@@ -159,8 +156,8 @@ export default class MWaterCompleteTableSelectComponent extends React.Component<
159
156
  return R(uiComponents.OptionListComponent, {
160
157
  items: _.map(sweetSenseTables, (table) => {
161
158
  return {
162
- name: ExprUtils.localizeString(table.name, this.context),
163
- desc: ExprUtils.localizeString(table.desc, this.context),
159
+ name: ExprUtils.localizeString(table.name, T.locale),
160
+ desc: ExprUtils.localizeString(table.desc, T.locale),
164
161
  onClick: this.props.onChange.bind(null, table.id)
165
162
  }
166
163
  })
@@ -177,7 +174,7 @@ export default class MWaterCompleteTableSelectComponent extends React.Component<
177
174
  extraTables: this.props.extraTables,
178
175
  onExtraTableAdd: this.handleExtraTableAdd,
179
176
  onExtraTableRemove: this.handleExtraTableRemove,
180
- locale: this.context
177
+ locale: T.locale
181
178
  })
182
179
  }
183
180
 
@@ -191,7 +188,7 @@ export default class MWaterCompleteTableSelectComponent extends React.Component<
191
188
  extraTables: this.props.extraTables,
192
189
  onExtraTableAdd: this.handleExtraTableAdd,
193
190
  onExtraTableRemove: this.handleExtraTableRemove,
194
- locale: this.context
191
+ locale: T.locale
195
192
  })
196
193
  }
197
194
 
@@ -208,8 +205,8 @@ export default class MWaterCompleteTableSelectComponent extends React.Component<
208
205
  continue
209
206
  }
210
207
  items.push({
211
- name: ExprUtils.localizeString(table.name, this.context),
212
- desc: ExprUtils.localizeString(table.desc, this.context),
208
+ name: ExprUtils.localizeString(table.name, T.locale),
209
+ desc: ExprUtils.localizeString(table.desc, T.locale),
213
210
  onClick: this.props.onChange.bind(null, table.id)
214
211
  })
215
212
  }
@@ -236,7 +233,7 @@ export default class MWaterCompleteTableSelectComponent extends React.Component<
236
233
  extraTables: this.props.extraTables,
237
234
  onExtraTableAdd: this.handleExtraTableAdd,
238
235
  onExtraTableRemove: this.handleExtraTableRemove,
239
- locale: this.context
236
+ locale: T.locale
240
237
  })
241
238
  }
242
239
 
@@ -294,8 +291,8 @@ export default class MWaterCompleteTableSelectComponent extends React.Component<
294
291
  return R(uiComponents.OptionListComponent, {
295
292
  items: _.map(otherTables, (table) => {
296
293
  return {
297
- name: ExprUtils.localizeString(table.name, this.context),
298
- desc: ExprUtils.localizeString(table.desc, this.context),
294
+ name: ExprUtils.localizeString(table.name, T.locale),
295
+ desc: ExprUtils.localizeString(table.desc, T.locale),
299
296
  onClick: this.props.onChange.bind(null, table.id)
300
297
  }
301
298
  })
@@ -320,25 +317,25 @@ export default class MWaterCompleteTableSelectComponent extends React.Component<
320
317
  const sweetSenseTables = this.getSweetSenseTables()
321
318
 
322
319
  const tabs: TabbedComponentTab[] = [
323
- { id: "sites", label: [R("i", { className: "fa fa-map-marker" }), T` Sites`], elem: this.renderSites() },
324
- { id: "forms", label: [R("i", { className: "fa fa-th-list" }), T` Surveys`], elem: this.renderForms() },
320
+ { id: "sites", label: [R("i", { className: "fa fa-map-marker" }), " ", T`Sites`], elem: this.renderSites() },
321
+ { id: "forms", label: [R("i", { className: "fa fa-th-list" }), " ", T`Surveys`], elem: this.renderForms() },
325
322
  {
326
323
  id: "indicators",
327
- label: [R("i", { className: "fa fa-check-circle" }), T` Indicators`],
324
+ label: [R("i", { className: "fa fa-check-circle" }), " ", T`Indicators`],
328
325
  elem: this.renderIndicators()
329
326
  },
330
327
  {
331
328
  id: "issues",
332
- label: [R("i", { className: "fa fa-exclamation-circle" }), T` Issues`],
329
+ label: [R("i", { className: "fa fa-exclamation-circle" }), " ", T`Issues`],
333
330
  elem: this.renderIssues()
334
331
  },
335
- { id: "tablesets", label: [R("i", { className: "fa fa-table" }), T` Tables`], elem: this.renderTablesets() },
336
- { id: "metrics", label: [R("i", { className: "fa fa-line-chart" }), T` Metrics`], elem: this.renderMetrics() },
337
- { id: "assets", label: [R("i", { className: "fas fa-map-pin" }), T` Assets`], elem: this.renderAssets() }
332
+ { id: "tablesets", label: [R("i", { className: "fa fa-table" }), " ", T`Tables`], elem: this.renderTablesets() },
333
+ { id: "metrics", label: [R("i", { className: "fa fa-line-chart" }), " ", T`Metrics`], elem: this.renderMetrics() },
334
+ { id: "assets", label: [R("i", { className: "fas fa-map-pin" }), " ", T`Assets`], elem: this.renderAssets() }
338
335
  ]
339
336
 
340
337
  if (sweetSenseTables.length > 0) {
341
- tabs.push({ id: "sensors", label: T` Sensors`, elem: this.renderSweetSense() })
338
+ tabs.push({ id: "sensors", label: T`Sensors`, elem: this.renderSweetSense() })
342
339
  }
343
340
 
344
341
  tabs.push({ id: "other", label: T`Advanced`, elem: this.renderOther() })
@@ -383,8 +380,6 @@ interface FormsListComponentState {
383
380
 
384
381
  // Searchable list of forms
385
382
  class FormsListComponent extends React.Component<FormsListComponentProps, FormsListComponentState> {
386
- static contextType = LocaleContext
387
-
388
383
  constructor(props: any) {
389
384
  super(props)
390
385
  this.state = {
@@ -447,7 +442,7 @@ class FormsListComponent extends React.Component<FormsListComponentProps, FormsL
447
442
  confirm(
448
443
  T`Remove ${ExprUtils.localizeString(
449
444
  table.name,
450
- this.context
445
+ T.locale
451
446
  )}? Any widgets that depend on it will no longer work properly.`
452
447
  )
453
448
  ) {
@@ -496,8 +491,8 @@ class FormsListComponent extends React.Component<FormsListComponentProps, FormsL
496
491
  ? R(uiComponents.OptionListComponent, {
497
492
  items: _.map(tables, (table) => {
498
493
  return {
499
- name: ExprUtils.localizeString(table.name, this.context),
500
- desc: ExprUtils.localizeString(table.desc, this.context),
494
+ name: ExprUtils.localizeString(table.name, T.locale),
495
+ desc: ExprUtils.localizeString(table.desc, T.locale),
501
496
  onClick: this.props.onChange.bind(null, table.id),
502
497
  onRemove: this.handleTableRemove.bind(null, table)
503
498
  }
@@ -562,7 +557,6 @@ interface IndicatorsListComponentState {
562
557
 
563
558
  // Searchable list of indicators
564
559
  class IndicatorsListComponent extends React.Component<IndicatorsListComponentProps, IndicatorsListComponentState> {
565
- static contextType = LocaleContext
566
560
  addIndicatorConfirmPopup: AddIndicatorConfirmPopupComponent | null
567
561
 
568
562
  constructor(props: any) {
@@ -590,7 +584,7 @@ class IndicatorsListComponent extends React.Component<IndicatorsListComponentPro
590
584
  [
591
585
  (indicator: any) => ((this.props.extraTables || []).includes("indicator_values:" + indicator._id) ? 0 : 1),
592
586
  (indicator: any) => (indicator.design.recommended ? 0 : 1),
593
- (indicator: any) => ExprUtils.localizeString(indicator.design.name, this.context)
587
+ (indicator: any) => ExprUtils.localizeString(indicator.design.name, T.locale)
594
588
  ],
595
589
  ["asc", "asc", "asc"]
596
590
  )
@@ -598,8 +592,8 @@ class IndicatorsListComponent extends React.Component<IndicatorsListComponentPro
598
592
  return this.setState({
599
593
  indicators: _.map(indicators, (indicator) => ({
600
594
  id: indicator._id,
601
- name: ExprUtils.localizeString(indicator.design.name, this.context),
602
- desc: ExprUtils.localizeString(indicator.design.desc, this.context)
595
+ name: ExprUtils.localizeString(indicator.design.name, T.locale),
596
+ desc: ExprUtils.localizeString(indicator.design.desc, T.locale)
603
597
  }))
604
598
  })
605
599
  }).fail((xhr: any) => {
@@ -612,7 +606,7 @@ class IndicatorsListComponent extends React.Component<IndicatorsListComponentPro
612
606
  confirm(
613
607
  T`Remove ${ExprUtils.localizeString(
614
608
  table.name,
615
- this.context
609
+ T.locale
616
610
  )}? Any widgets that depend on it will no longer work properly.`
617
611
  )
618
612
  ) {
@@ -679,8 +673,8 @@ class IndicatorsListComponent extends React.Component<IndicatorsListComponentPro
679
673
  ? R(uiComponents.OptionListComponent, {
680
674
  items: _.map(tables, (table) => {
681
675
  return {
682
- name: ExprUtils.localizeString(table.name, this.context),
683
- desc: ExprUtils.localizeString(table.desc, this.context),
676
+ name: ExprUtils.localizeString(table.name, T.locale),
677
+ desc: ExprUtils.localizeString(table.desc, T.locale),
684
678
  onClick: this.handleSelect.bind(null, table.id),
685
679
  onRemove: this.handleTableRemove.bind(null, table)
686
680
  }
@@ -738,8 +732,6 @@ class AddIndicatorConfirmPopupComponent extends React.Component<
738
732
  AddIndicatorConfirmPopupComponentProps,
739
733
  AddIndicatorConfirmPopupComponentState
740
734
  > {
741
- static contextType = LocaleContext
742
-
743
735
  constructor(props: any) {
744
736
  super(props)
745
737
  this.state = {
@@ -781,8 +773,8 @@ are certain that you want to use the raw indicator table`
781
773
 
782
774
  R(uiComponents.OptionListComponent, {
783
775
  items: _.map(entityColumns, (entityColumn) => ({
784
- name: ExprUtils.localizeString(entityColumn.name, this.context),
785
- desc: ExprUtils.localizeString(entityColumn.desc, this.context),
776
+ name: ExprUtils.localizeString(entityColumn.name, T.locale),
777
+ desc: ExprUtils.localizeString(entityColumn.desc, T.locale),
786
778
  onClick: () => {
787
779
  // Select table
788
780
  this.props.onChange(entityColumn.join!.toTable)
@@ -845,8 +837,6 @@ interface IssuesListComponentState {
845
837
 
846
838
  // Searchable list of issue types
847
839
  class IssuesListComponent extends React.Component<IssuesListComponentProps, IssuesListComponentState> {
848
- static contextType = LocaleContext
849
-
850
840
  constructor(props: any) {
851
841
  super(props)
852
842
  this.state = {
@@ -869,7 +859,7 @@ class IssuesListComponent extends React.Component<IssuesListComponentProps, Issu
869
859
  [
870
860
  (issueType) => ((this.props.extraTables || []).includes("issues:" + issueType._id) ? 0 : 1),
871
861
  (issueType) => (issueType.created.by === this.props.user ? 0 : 1),
872
- (issueType) => ExprUtils.localizeString(issueType.name, this.context)
862
+ (issueType) => ExprUtils.localizeString(issueType.name, T.locale)
873
863
  ],
874
864
  ["asc", "asc", "asc"]
875
865
  )
@@ -877,8 +867,8 @@ class IssuesListComponent extends React.Component<IssuesListComponentProps, Issu
877
867
  return this.setState({
878
868
  issueTypes: _.map(issueTypes, (issueType) => ({
879
869
  id: issueType._id,
880
- name: ExprUtils.localizeString(issueType.name, this.context),
881
- desc: ExprUtils.localizeString(issueType.desc, this.context)
870
+ name: ExprUtils.localizeString(issueType.name, T.locale),
871
+ desc: ExprUtils.localizeString(issueType.desc, T.locale)
882
872
  }))
883
873
  })
884
874
  }).fail((xhr: any) => {
@@ -891,7 +881,7 @@ class IssuesListComponent extends React.Component<IssuesListComponentProps, Issu
891
881
  confirm(
892
882
  T`Remove ${ExprUtils.localizeString(
893
883
  table.name,
894
- this.context
884
+ T.locale
895
885
  )}? Any widgets that depend on it will no longer work properly.`
896
886
  )
897
887
  ) {
@@ -940,8 +930,8 @@ class IssuesListComponent extends React.Component<IssuesListComponentProps, Issu
940
930
  ? R(uiComponents.OptionListComponent, {
941
931
  items: _.map(tables, (table) => {
942
932
  return {
943
- name: ExprUtils.localizeString(table.name, this.context),
944
- desc: ExprUtils.localizeString(table.desc, this.context),
933
+ name: ExprUtils.localizeString(table.name, T.locale),
934
+ desc: ExprUtils.localizeString(table.desc, T.locale),
945
935
  onClick: this.props.onChange.bind(null, table.id),
946
936
  onRemove: this.handleTableRemove.bind(null, table)
947
937
  }
@@ -8,34 +8,36 @@ import LoadingComponent from "@mwater/react-library/lib/LoadingComponent"
8
8
  import mWaterLoader from "./mWaterLoader"
9
9
  import MWaterContextComponent, { AddLayerElementFactory } from "./MWaterContextComponent"
10
10
 
11
+ export interface MWaterLoaderComponentProps {
12
+ apiUrl: string
13
+ client?: string
14
+ share?: string
15
+ /** user id of logged in user */
16
+ user?: string
17
+ /** Load schema as a specific user (for shared dashboards, etc) */
18
+ asUser?: string
19
+ /** Extra tables to load in schema. Forms are not loaded by default as they are too many */
20
+ extraTables?: string[]
21
+ /** Called when extra tables are changed and schema will be reloaded */
22
+ onExtraTablesChange?: (extraTables: string[]) => void
23
+ /** Locales of the schema to load. Default is all. */
24
+ locales?: string[]
25
+ /** Override default add layer component. See AddLayerComponent for details */
26
+ addLayerElementFactory?: AddLayerElementFactory
27
+ children: (error: any, config?: { schema: Schema; dataSource: DataSource }) => ReactElement<any>
28
+ /** Custom error formatter that returns React node or string, gets passed the error response from server */
29
+ errorFormatter?: (data: any, defaultError: string) => string
30
+ /** Origin of usage. e.g. "dashboards:43445364..." */
31
+ origin?: string
32
+ }
33
+
11
34
  /**
12
35
  * Loads an mWater schema from the server and creates child with schema and dataSource
13
36
  * Also creates context to allow selecting of a table in an mWater-friendly way
14
37
  * and several other context items
15
38
  */
16
39
  export default class MWaterLoaderComponent extends AsyncLoadComponent<
17
- {
18
- apiUrl: string
19
- client?: string
20
- share?: string
21
- /** user id of logged in user */
22
- user?: string
23
- /** Load schema as a specific user (for shared dashboards, etc) */
24
- asUser?: string
25
- /** Extra tables to load in schema. Forms are not loaded by default as they are too many */
26
- extraTables?: string[]
27
- /** Called when extra tables are changed and schema will be reloaded */
28
- onExtraTablesChange?: (extraTables: string[]) => void
29
- /** Locales of the schema to load. Default is all. */
30
- locales?: string[]
31
- /** Override default add layer component. See AddLayerComponent for details */
32
- addLayerElementFactory?: AddLayerElementFactory
33
- children: (error: any, config?: { schema: Schema; dataSource: DataSource }) => ReactElement<any>
34
- /** Custom error formatter that returns React node or string, gets passed the error response from server */
35
- errorFormatter?: (data: any, defaultError: string) => string
36
- /** Origin of usage. e.g. "dashboards:43445364..." */
37
- origin?: string
38
- },
40
+ MWaterLoaderComponentProps,
39
41
  {
40
42
  error: any
41
43
  schema: Schema | null
@@ -45,7 +47,7 @@ export default class MWaterLoaderComponent extends AsyncLoadComponent<
45
47
  > {
46
48
  mounted: boolean
47
49
 
48
- constructor(props: any) {
50
+ constructor(props: MWaterLoaderComponentProps) {
49
51
  super(props)
50
52
  this.state = {
51
53
  error: null,
@@ -58,7 +60,7 @@ export default class MWaterLoaderComponent extends AsyncLoadComponent<
58
60
  }
59
61
 
60
62
  // Override to determine if a load is needed. Not called on mounting
61
- isLoadNeeded(newProps: any, oldProps: any) {
63
+ isLoadNeeded(newProps: MWaterLoaderComponentProps, oldProps: MWaterLoaderComponentProps) {
62
64
  return !_.isEqual(
63
65
  _.pick(newProps, "apiUrl", "client", "user", "share", "asUser", "extraTables", "locales"),
64
66
  _.pick(oldProps, "apiUrl", "client", "user", "share", "asUser", "extraTables", "locales")
@@ -66,9 +68,9 @@ export default class MWaterLoaderComponent extends AsyncLoadComponent<
66
68
  }
67
69
 
68
70
  // Call callback with state changes
69
- load(props: any, prevProps: any, callback: any) {
71
+ load(props: MWaterLoaderComponentProps, prevProps: MWaterLoaderComponentProps, callback: any) {
70
72
  // Load schema and data source
71
- return mWaterLoader(
73
+ mWaterLoader(
72
74
  {
73
75
  apiUrl: props.apiUrl,
74
76
  client: props.client,
@@ -173,9 +173,12 @@ export default class MWaterResponsesFilterComponent extends React.Component<MWat
173
173
  return R(
174
174
  ui.Radio,
175
175
  { key: column.id, value: siteColumnId, radioValue: column.id, onChange: this.handleSiteChange },
176
- T`Show only the latest response for each `,
176
+ T`Show only the latest response for each`,
177
+ " ",
177
178
  R("i", null, `${ExprUtils.localizeString(this.props.schema.getTable(column.join.toTable)?.name)}`),
178
- T` in the question `,
179
+ " ",
180
+ T`in the question`,
181
+ " ",
179
182
  R("i", null, `'${ExprUtils.localizeString(column.name)}'`)
180
183
  )
181
184
  })
@@ -6,7 +6,7 @@ import { ExprUtils, Schema } from "@mwater/expressions"
6
6
  import MWaterResponsesFilterComponent from "./MWaterResponsesFilterComponent"
7
7
  import ModalPopupComponent from "@mwater/react-library/lib/ModalPopupComponent"
8
8
  import MWaterCompleteTableSelectComponent from "./MWaterCompleteTableSelectComponent"
9
- import { ActiveTablesContext, LocaleContext } from "@mwater/expressions-ui"
9
+ import { ActiveTablesContext } from "@mwater/expressions-ui"
10
10
 
11
11
  export interface MWaterTableSelectComponentProps {
12
12
  /** Url to hit api */
@@ -35,8 +35,6 @@ export default class MWaterTableSelectComponent extends React.Component<
35
35
  MWaterTableSelectComponentProps,
36
36
  MWaterTableSelectComponentState
37
37
  > {
38
- static contextType = LocaleContext
39
-
40
38
  toggleEdit: any
41
39
 
42
40
  constructor(props: MWaterTableSelectComponentProps) {
@@ -136,7 +134,7 @@ export default class MWaterTableSelectComponent extends React.Component<
136
134
  },
137
135
  forceOpen: !this.props.table, // Must have table
138
136
  label: this.props.table
139
- ? ExprUtils.localizeString(this.props.schema.getTable(this.props.table)?.name, this.context)
137
+ ? ExprUtils.localizeString(this.props.schema.getTable(this.props.table)?.name, T.locale)
140
138
  : "",
141
139
  editor,
142
140
  onRemove: () => {
@@ -184,8 +182,6 @@ class EditModeTableSelectComponent extends React.Component<
184
182
  EditModeTableSelectComponentProps,
185
183
  EditModeTableSelectComponentState
186
184
  > {
187
- static contextType = LocaleContext
188
-
189
185
  constructor(props: any) {
190
186
  super(props)
191
187
 
@@ -235,7 +231,7 @@ class EditModeTableSelectComponent extends React.Component<
235
231
 
236
232
  // Sort by name
237
233
  tables = _.sortBy(tables, (tableId) =>
238
- ExprUtils.localizeString(this.props.schema.getTable(tableId)!.name, this.context)
234
+ ExprUtils.localizeString(this.props.schema.getTable(tableId)!.name, T.locale)
239
235
  )
240
236
 
241
237
  return tables
@@ -277,8 +273,8 @@ class EditModeTableSelectComponent extends React.Component<
277
273
  <OptionListComponent items={this.getTableShortlist(activeTables).map((tableId) => {
278
274
  const table = this.props.schema.getTable(tableId)!
279
275
  return {
280
- name: ExprUtils.localizeString(table.name, this.context),
281
- desc: ExprUtils.localizeString(table.desc, this.context),
276
+ name: ExprUtils.localizeString(table.name, T.locale),
277
+ desc: ExprUtils.localizeString(table.desc, T.locale),
282
278
  onClick: () => this.props.onChange(table.id)
283
279
  }
284
280
  })} />
@@ -0,0 +1,141 @@
1
+ import { LocalizedString, Locale } from "ez-localize/lib/utils"
2
+
3
+ /** Translates an array of strings from a source language to a target language using the mWater translation API.
4
+ * @param strings Array of strings to translate
5
+ * @param sourceLanguage Source language code (e.g. "en")
6
+ * @param targetLanguage Target language code to translate to
7
+ * @returns Promise that resolves to array of translated strings in same order as input
8
+ * @throws Error if translation fails
9
+ */
10
+ export async function translateStrings(
11
+ strings: string[],
12
+ sourceLanguage: string,
13
+ targetLanguage: string
14
+ ): Promise<string[]> {
15
+ // Call translation API
16
+ const response = await fetch(
17
+ `https://api.mwater.co/v3/translate?source_language=${sourceLanguage}&target_language=${targetLanguage}`,
18
+ {
19
+ method: "POST",
20
+ headers: {
21
+ "Content-Type": "application/json"
22
+ },
23
+ body: JSON.stringify({
24
+ phrases: strings
25
+ })
26
+ }
27
+ )
28
+
29
+ if (!response.ok) {
30
+ throw new Error("Translation failed")
31
+ }
32
+
33
+ const result = await response.json()
34
+ return result.phrases
35
+ }
36
+
37
+ /** Ensures that all LocalizedString objects have translations for all specified locales.
38
+ * Only translates missing translations, preserving existing ones and base strings.
39
+ * Each string's _base property is used as the source language for translations.
40
+ * @param strings Array of LocalizedString objects to ensure are fully translated
41
+ * @param locales Array of language codes specifying which languages to ensure exist
42
+ * @param baseLanguage Language code of the _base strings (e.g. "en", "fr", etc)
43
+ * @returns Promise that resolves to array of fully translated LocalizedString objects
44
+ */
45
+ export async function translateLocalizedStrings(
46
+ strings: LocalizedString[],
47
+ locales: string[],
48
+ baseLanguage: string
49
+ ): Promise<LocalizedString[]> {
50
+ // Create copy of strings to modify
51
+ const translatedStrings = strings.map(str => ({ ...str }))
52
+
53
+ // For each locale
54
+ for (const locale of locales) {
55
+ // Skip if it's the base language
56
+ if (locale === baseLanguage) {
57
+ continue
58
+ }
59
+
60
+ // Group strings by their current source language
61
+ // Start with base language strings
62
+ const stringsBySourceLang = new Map<string, { str: LocalizedString; index: number }[]>()
63
+
64
+ translatedStrings.forEach((str, index) => {
65
+ // Skip if translation already exists
66
+ if (str[locale]) {
67
+ return
68
+ }
69
+
70
+ // Add to list to translate from base language
71
+ if (!stringsBySourceLang.has(baseLanguage)) {
72
+ stringsBySourceLang.set(baseLanguage, [])
73
+ }
74
+ stringsBySourceLang.get(baseLanguage)!.push({ str, index })
75
+ })
76
+
77
+ // Translate each group
78
+ for (const [sourceLang, stringsToTranslate] of stringsBySourceLang.entries()) {
79
+ try {
80
+ // Get source strings
81
+ const sourceStrings = stringsToTranslate.map(item => item.str[item.str._base])
82
+
83
+ // Translate all strings at once
84
+ const translations = await translateStrings(sourceStrings, sourceLang, locale)
85
+
86
+ // Add translations back to strings
87
+ translations.forEach((translation, i) => {
88
+ translatedStrings[stringsToTranslate[i].index][locale] = translation
89
+ })
90
+ } catch (error) {
91
+ console.error(`Failed to translate from ${sourceLang} to ${locale}:`, error)
92
+ throw error
93
+ }
94
+ }
95
+ }
96
+
97
+ return translatedStrings
98
+ }
99
+
100
+ /** Returns true if the given language code can be automatically translated. */
101
+ export function canAutoTranslate(languageCode: string) {
102
+ const languageCodes = [
103
+ "en", // English
104
+ "fr", // French
105
+ "es", // Spanish
106
+ "pt", // Portuguese
107
+ "sw", // Swahili
108
+ "id", // Indonesian
109
+ "hi", // Hindi
110
+ "ne", // Nepali
111
+ "rw", // Kinyarwanda
112
+ "sd", // Sindhi
113
+ "tet", // Tetum
114
+ "ur", // Urdu
115
+ "ja", // Japanese
116
+ "de", // German
117
+ "it", // Italian
118
+ "su", // Sundanese
119
+ "ar", // Arabic
120
+ "vi", // Vietnamese
121
+ "mg", // Malagasy
122
+ "tl", // Tagalog/Filipino
123
+ "ht", // Haitian Creole
124
+ "fi", // Finnish
125
+ "bn", // Bangla
126
+ "my", // Burmese
127
+ "km", // Khmer
128
+ "so", // Somali
129
+ "jv", // Javanese
130
+ "ko", // Korean
131
+ "zh", // Chinese
132
+ "ru", // Russian
133
+ "tr", // Turkish
134
+ "nl", // Dutch
135
+ "pl", // Polish
136
+ "hu", // Hungarian
137
+ "cs", // Czech
138
+ "sk" // Slovak
139
+ ]
140
+ return languageCodes.includes(languageCode)
141
+ }
@@ -532,7 +532,7 @@ export default class AxisBuilder {
532
532
 
533
533
  if (range.maxValue != null) {
534
534
  if (label) {
535
- label += T` and `
535
+ label += ` ${T`and`} `
536
536
  }
537
537
  if (range.maxOpen) {
538
538
  label += `< ${range.maxValue}`
@@ -1024,7 +1024,7 @@ export default class AxisBuilder {
1024
1024
  if (category) {
1025
1025
  return this.formatCategory(axis, category)
1026
1026
  } else {
1027
- return T`???`
1027
+ return `???`
1028
1028
  }
1029
1029
  }).join(", ")
1030
1030
  } else {
@@ -1032,7 +1032,7 @@ export default class AxisBuilder {
1032
1032
  if (category) {
1033
1033
  return this.formatCategory(axis, category)
1034
1034
  } else {
1035
- return T`???`
1035
+ return `???`
1036
1036
  }
1037
1037
  }
1038
1038
  }