waha-shared 1.0.481 → 1.0.482
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.
- package/dist/data/bibleStatuses/bibleStatuses.json +290 -0
- package/dist/data/languages/languages.json +7 -3
- package/dist/data/mediaDurations/mediaDurations.json +888 -0
- package/dist/data/releaseNotes/releaseNotes.json +64 -2
- package/dist/data/translationsApp/index.d.ts +0 -16
- package/dist/data/translationsApp/translationsApp.json +434 -656
- package/dist/data/translationsApp/translationsApp.schema.json +0 -18
- package/dist/data/translationsApp/translationsApp.zod.d.ts +0 -46
- package/dist/data/translationsApp/translationsApp.zod.js +2 -17
- package/dist/functions/crowdin.d.ts +41 -2
- package/dist/functions/crowdin.js +122 -5
- package/dist/types/dripSequence.d.ts +27 -0
- package/dist/types/dripSequence.js +17 -0
- package/dist/types/microLessons.d.ts +1 -1
- package/dist/types/users.d.ts +4 -4
- package/package.json +2 -1
|
@@ -17,22 +17,8 @@
|
|
|
17
17
|
"some": { "type": "string" },
|
|
18
18
|
"none": { "type": "string" },
|
|
19
19
|
"highlight_verse": { "type": "string" },
|
|
20
|
-
"join_others_discovering": { "type": "string" },
|
|
21
20
|
"people_shared_last_week": { "type": "string" },
|
|
22
|
-
"onboarding_dbs_intro_heading": { "type": "string" },
|
|
23
|
-
"onboarding_dbs_intro_body": { "type": "string" },
|
|
24
|
-
"onboarding_invite_group_heading": { "type": "string" },
|
|
25
|
-
"onboarding_invite_group_body": { "type": "string" },
|
|
26
|
-
"popups_need_help_with_group_title": { "type": "string" },
|
|
27
|
-
"popups_need_help_with_group_message": { "type": "string" },
|
|
28
21
|
"popups_micro_lessons_banner": { "type": "string" },
|
|
29
|
-
"question_in_a_group": { "type": "string" },
|
|
30
|
-
"question_what_brings_you_question": { "type": "string" },
|
|
31
|
-
"question_what_brings_you_body": { "type": "string" },
|
|
32
|
-
"question_what_brings_you_option_1": { "type": "string" },
|
|
33
|
-
"question_what_brings_you_option_2": { "type": "string" },
|
|
34
|
-
"question_what_brings_you_option_3": { "type": "string" },
|
|
35
|
-
"question_what_brings_you_option_4": { "type": "string" },
|
|
36
22
|
"name": { "type": "string", "minLength": 1 },
|
|
37
23
|
"version": { "type": "string", "minLength": 1 },
|
|
38
24
|
"a11y_add_secondary_language_hint": {
|
|
@@ -519,11 +505,9 @@
|
|
|
519
505
|
"article": { "type": "string", "minLength": 1 },
|
|
520
506
|
"no_results": { "type": "string", "minLength": 1 },
|
|
521
507
|
"no_notes": { "type": "string", "minLength": 1 },
|
|
522
|
-
"not_yet": { "type": "string", "minLength": 1 },
|
|
523
508
|
"micro_lesson": { "type": "string", "minLength": 1 },
|
|
524
509
|
"micro_lessons": { "type": "string", "minLength": 1 },
|
|
525
510
|
"filter_micro_lessons": { "type": "string", "minLength": 1 },
|
|
526
|
-
"question_placeholder": { "type": "string", "minLength": 1 },
|
|
527
511
|
"no_text_available": { "type": "string" },
|
|
528
512
|
"share_story_audio": { "type": "string" },
|
|
529
513
|
"read_along": { "type": "string" },
|
|
@@ -871,11 +855,9 @@
|
|
|
871
855
|
"article",
|
|
872
856
|
"no_results",
|
|
873
857
|
"no_notes",
|
|
874
|
-
"not_yet",
|
|
875
858
|
"micro_lesson",
|
|
876
859
|
"micro_lessons",
|
|
877
860
|
"filter_micro_lessons",
|
|
878
|
-
"question_placeholder",
|
|
879
861
|
"no_text_available",
|
|
880
862
|
"share_story_audio",
|
|
881
863
|
"read_along",
|
|
@@ -13,22 +13,8 @@ export declare const TrickyStrings: z.ZodObject<{
|
|
|
13
13
|
some: z.ZodOptional<z.ZodString>;
|
|
14
14
|
none: z.ZodOptional<z.ZodString>;
|
|
15
15
|
highlight_verse: z.ZodOptional<z.ZodString>;
|
|
16
|
-
join_others_discovering: z.ZodOptional<z.ZodString>;
|
|
17
16
|
people_shared_last_week: z.ZodOptional<z.ZodString>;
|
|
18
|
-
onboarding_dbs_intro_heading: z.ZodOptional<z.ZodString>;
|
|
19
|
-
onboarding_dbs_intro_body: z.ZodOptional<z.ZodString>;
|
|
20
|
-
onboarding_invite_group_heading: z.ZodOptional<z.ZodString>;
|
|
21
|
-
onboarding_invite_group_body: z.ZodOptional<z.ZodString>;
|
|
22
|
-
popups_need_help_with_group_title: z.ZodOptional<z.ZodString>;
|
|
23
|
-
popups_need_help_with_group_message: z.ZodOptional<z.ZodString>;
|
|
24
17
|
popups_micro_lessons_banner: z.ZodOptional<z.ZodString>;
|
|
25
|
-
question_in_a_group: z.ZodOptional<z.ZodString>;
|
|
26
|
-
question_what_brings_you_question: z.ZodOptional<z.ZodString>;
|
|
27
|
-
question_what_brings_you_body: z.ZodOptional<z.ZodString>;
|
|
28
|
-
question_what_brings_you_option_1: z.ZodOptional<z.ZodString>;
|
|
29
|
-
question_what_brings_you_option_2: z.ZodOptional<z.ZodString>;
|
|
30
|
-
question_what_brings_you_option_3: z.ZodOptional<z.ZodString>;
|
|
31
|
-
question_what_brings_you_option_4: z.ZodOptional<z.ZodString>;
|
|
32
18
|
}, z.core.$strip>;
|
|
33
19
|
export declare const LanguageTranslationsApp: z.ZodObject<{
|
|
34
20
|
name: z.ZodString;
|
|
@@ -338,11 +324,9 @@ export declare const LanguageTranslationsApp: z.ZodObject<{
|
|
|
338
324
|
article: z.ZodString;
|
|
339
325
|
no_results: z.ZodString;
|
|
340
326
|
no_notes: z.ZodString;
|
|
341
|
-
not_yet: z.ZodString;
|
|
342
327
|
micro_lesson: z.ZodString;
|
|
343
328
|
micro_lessons: z.ZodString;
|
|
344
329
|
filter_micro_lessons: z.ZodString;
|
|
345
|
-
question_placeholder: z.ZodString;
|
|
346
330
|
no_text_available: z.ZodString;
|
|
347
331
|
share_story_audio: z.ZodString;
|
|
348
332
|
read_along: z.ZodString;
|
|
@@ -387,22 +371,8 @@ export declare const LanguageTranslationsApp: z.ZodObject<{
|
|
|
387
371
|
some: z.ZodOptional<z.ZodString>;
|
|
388
372
|
none: z.ZodOptional<z.ZodString>;
|
|
389
373
|
highlight_verse: z.ZodOptional<z.ZodString>;
|
|
390
|
-
join_others_discovering: z.ZodOptional<z.ZodString>;
|
|
391
374
|
people_shared_last_week: z.ZodOptional<z.ZodString>;
|
|
392
|
-
onboarding_dbs_intro_heading: z.ZodOptional<z.ZodString>;
|
|
393
|
-
onboarding_dbs_intro_body: z.ZodOptional<z.ZodString>;
|
|
394
|
-
onboarding_invite_group_heading: z.ZodOptional<z.ZodString>;
|
|
395
|
-
onboarding_invite_group_body: z.ZodOptional<z.ZodString>;
|
|
396
|
-
popups_need_help_with_group_title: z.ZodOptional<z.ZodString>;
|
|
397
|
-
popups_need_help_with_group_message: z.ZodOptional<z.ZodString>;
|
|
398
375
|
popups_micro_lessons_banner: z.ZodOptional<z.ZodString>;
|
|
399
|
-
question_in_a_group: z.ZodOptional<z.ZodString>;
|
|
400
|
-
question_what_brings_you_question: z.ZodOptional<z.ZodString>;
|
|
401
|
-
question_what_brings_you_body: z.ZodOptional<z.ZodString>;
|
|
402
|
-
question_what_brings_you_option_1: z.ZodOptional<z.ZodString>;
|
|
403
|
-
question_what_brings_you_option_2: z.ZodOptional<z.ZodString>;
|
|
404
|
-
question_what_brings_you_option_3: z.ZodOptional<z.ZodString>;
|
|
405
|
-
question_what_brings_you_option_4: z.ZodOptional<z.ZodString>;
|
|
406
376
|
}, z.core.$strip>;
|
|
407
377
|
export type LanguageTranslationsApp = z.infer<typeof LanguageTranslationsApp>;
|
|
408
378
|
export declare const TranslationsApp: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
@@ -713,11 +683,9 @@ export declare const TranslationsApp: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
|
713
683
|
article: z.ZodString;
|
|
714
684
|
no_results: z.ZodString;
|
|
715
685
|
no_notes: z.ZodString;
|
|
716
|
-
not_yet: z.ZodString;
|
|
717
686
|
micro_lesson: z.ZodString;
|
|
718
687
|
micro_lessons: z.ZodString;
|
|
719
688
|
filter_micro_lessons: z.ZodString;
|
|
720
|
-
question_placeholder: z.ZodString;
|
|
721
689
|
no_text_available: z.ZodString;
|
|
722
690
|
share_story_audio: z.ZodString;
|
|
723
691
|
read_along: z.ZodString;
|
|
@@ -762,21 +730,7 @@ export declare const TranslationsApp: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
|
762
730
|
some: z.ZodOptional<z.ZodString>;
|
|
763
731
|
none: z.ZodOptional<z.ZodString>;
|
|
764
732
|
highlight_verse: z.ZodOptional<z.ZodString>;
|
|
765
|
-
join_others_discovering: z.ZodOptional<z.ZodString>;
|
|
766
733
|
people_shared_last_week: z.ZodOptional<z.ZodString>;
|
|
767
|
-
onboarding_dbs_intro_heading: z.ZodOptional<z.ZodString>;
|
|
768
|
-
onboarding_dbs_intro_body: z.ZodOptional<z.ZodString>;
|
|
769
|
-
onboarding_invite_group_heading: z.ZodOptional<z.ZodString>;
|
|
770
|
-
onboarding_invite_group_body: z.ZodOptional<z.ZodString>;
|
|
771
|
-
popups_need_help_with_group_title: z.ZodOptional<z.ZodString>;
|
|
772
|
-
popups_need_help_with_group_message: z.ZodOptional<z.ZodString>;
|
|
773
734
|
popups_micro_lessons_banner: z.ZodOptional<z.ZodString>;
|
|
774
|
-
question_in_a_group: z.ZodOptional<z.ZodString>;
|
|
775
|
-
question_what_brings_you_question: z.ZodOptional<z.ZodString>;
|
|
776
|
-
question_what_brings_you_body: z.ZodOptional<z.ZodString>;
|
|
777
|
-
question_what_brings_you_option_1: z.ZodOptional<z.ZodString>;
|
|
778
|
-
question_what_brings_you_option_2: z.ZodOptional<z.ZodString>;
|
|
779
|
-
question_what_brings_you_option_3: z.ZodOptional<z.ZodString>;
|
|
780
|
-
question_what_brings_you_option_4: z.ZodOptional<z.ZodString>;
|
|
781
735
|
}, z.core.$strip>>;
|
|
782
736
|
export type TranslationsApp = z.infer<typeof TranslationsApp>;
|
|
@@ -19,23 +19,10 @@ exports.TrickyStrings = zod_1.z
|
|
|
19
19
|
none: zod_1.z.string(),
|
|
20
20
|
// Verse highlighting
|
|
21
21
|
highlight_verse: zod_1.z.string(),
|
|
22
|
-
//
|
|
23
|
-
join_others_discovering: zod_1.z.string(),
|
|
22
|
+
// Sharing social proof
|
|
24
23
|
people_shared_last_week: zod_1.z.string(),
|
|
25
|
-
|
|
26
|
-
onboarding_dbs_intro_body: zod_1.z.string(),
|
|
27
|
-
onboarding_invite_group_heading: zod_1.z.string(),
|
|
28
|
-
onboarding_invite_group_body: zod_1.z.string(),
|
|
29
|
-
popups_need_help_with_group_title: zod_1.z.string(),
|
|
30
|
-
popups_need_help_with_group_message: zod_1.z.string(),
|
|
24
|
+
// Micro lessons
|
|
31
25
|
popups_micro_lessons_banner: zod_1.z.string(),
|
|
32
|
-
question_in_a_group: zod_1.z.string(),
|
|
33
|
-
question_what_brings_you_question: zod_1.z.string(),
|
|
34
|
-
question_what_brings_you_body: zod_1.z.string(),
|
|
35
|
-
question_what_brings_you_option_1: zod_1.z.string(),
|
|
36
|
-
question_what_brings_you_option_2: zod_1.z.string(),
|
|
37
|
-
question_what_brings_you_option_3: zod_1.z.string(),
|
|
38
|
-
question_what_brings_you_option_4: zod_1.z.string(),
|
|
39
26
|
})
|
|
40
27
|
.partial();
|
|
41
28
|
exports.LanguageTranslationsApp = zod_1.z.object({
|
|
@@ -349,11 +336,9 @@ exports.LanguageTranslationsApp = zod_1.z.object({
|
|
|
349
336
|
article: zod_1.z.string().min(1),
|
|
350
337
|
no_results: zod_1.z.string().min(1),
|
|
351
338
|
no_notes: zod_1.z.string().min(1),
|
|
352
|
-
not_yet: zod_1.z.string().min(1),
|
|
353
339
|
micro_lesson: zod_1.z.string().min(1),
|
|
354
340
|
micro_lessons: zod_1.z.string().min(1),
|
|
355
341
|
filter_micro_lessons: zod_1.z.string().min(1),
|
|
356
|
-
question_placeholder: zod_1.z.string().min(1),
|
|
357
342
|
no_text_available: zod_1.z.string(),
|
|
358
343
|
// ---
|
|
359
344
|
// Auth feature
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type SourceFilesModel } from '@crowdin/crowdin-api-client';
|
|
1
2
|
/**
|
|
2
3
|
* Map of project names to their Crowdin ids. Can be retrieved by going to the
|
|
3
4
|
* project's dashboard in Crowdin and looking on the right side panel for ID:
|
|
@@ -7,7 +8,14 @@ export declare const crowdinProjectIds: {
|
|
|
7
8
|
website: string;
|
|
8
9
|
app: string;
|
|
9
10
|
dmc: string;
|
|
11
|
+
emails: string;
|
|
10
12
|
};
|
|
13
|
+
/**
|
|
14
|
+
* Where a translated file lands, relative to the language folder. Every Waha
|
|
15
|
+
* project maps a language's Crowdin three-letter code onto its Waha id, which
|
|
16
|
+
* is why translations download straight into `crowdin/{wahaLanguageId}`.
|
|
17
|
+
*/
|
|
18
|
+
export declare const CROWDIN_TRANSLATION_PATTERN = "%three_letters_code%/%original_file_name%";
|
|
11
19
|
interface DownloadTranslationsParams {
|
|
12
20
|
/**
|
|
13
21
|
* The id of the project to download translations for. Can either be taken
|
|
@@ -17,14 +25,45 @@ interface DownloadTranslationsParams {
|
|
|
17
25
|
projectId: string;
|
|
18
26
|
/**
|
|
19
27
|
* The folder where translations are stored. Source translations are assumed
|
|
20
|
-
* to be stored in `translationsFolder/eng
|
|
28
|
+
* to be stored in `translationsFolder/eng/{sourcePattern}`.
|
|
21
29
|
*/
|
|
22
30
|
translationsFolder: string;
|
|
23
31
|
/** The Crowdin personal access token to use for authentication. */
|
|
24
32
|
token: string;
|
|
33
|
+
/**
|
|
34
|
+
* Glob matching the source files to download translations for, relative to
|
|
35
|
+
* `translationsFolder/eng`. Defaults to the JSON files every other project
|
|
36
|
+
* uses; the drip emails are markdown.
|
|
37
|
+
*/
|
|
38
|
+
sourcePattern?: string;
|
|
25
39
|
}
|
|
26
40
|
/**
|
|
27
41
|
* Downloads translations from Crowdin for a given project ID and source path.
|
|
28
42
|
*/
|
|
29
|
-
export declare function downloadTranslations({ projectId, translationsFolder, token, }: DownloadTranslationsParams): void;
|
|
43
|
+
export declare function downloadTranslations({ projectId, translationsFolder, token, sourcePattern, }: DownloadTranslationsParams): void;
|
|
44
|
+
interface UploadSourceParams {
|
|
45
|
+
/** The id of the project to upload to, from `crowdinProjectIds`. */
|
|
46
|
+
projectId: string;
|
|
47
|
+
/**
|
|
48
|
+
* Absolute path to the source file to upload, somewhere under a `crowdin/`
|
|
49
|
+
* directory (e.g. `/path/to/project/crowdin/eng/app_interface_text.json`,
|
|
50
|
+
* or `/path/to/project/crowdin/foo.md` for a project that keeps sources at
|
|
51
|
+
* the root). The path Crowdin sees is everything after `crowdin/`.
|
|
52
|
+
*/
|
|
53
|
+
source: string;
|
|
54
|
+
/** The Crowdin personal access token to use for authentication. */
|
|
55
|
+
token: string;
|
|
56
|
+
/**
|
|
57
|
+
* Label to attach, created if Crowdin has not seen it before. Only applies
|
|
58
|
+
* to new keys, which is what makes version tagging work.
|
|
59
|
+
*/
|
|
60
|
+
label?: string;
|
|
61
|
+
/** Parser and import settings, for files needing more than the defaults. */
|
|
62
|
+
fileSettings?: {
|
|
63
|
+
type?: SourceFilesModel.FileType;
|
|
64
|
+
importOptions?: SourceFilesModel.ImportOptions;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** Uploads a source file to Crowdin, creating it or replacing its contents. */
|
|
68
|
+
export declare function uploadSource({ projectId, source, token, label, fileSettings, }: UploadSourceParams): Promise<void>;
|
|
30
69
|
export {};
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.crowdinProjectIds = void 0;
|
|
6
|
+
exports.CROWDIN_TRANSLATION_PATTERN = exports.crowdinProjectIds = void 0;
|
|
4
7
|
exports.downloadTranslations = downloadTranslations;
|
|
8
|
+
exports.uploadSource = uploadSource;
|
|
9
|
+
const crowdin_api_client_1 = __importDefault(require("@crowdin/crowdin-api-client"));
|
|
10
|
+
const fs_1 = __importDefault(require("fs"));
|
|
5
11
|
const node_child_process_1 = require("node:child_process");
|
|
12
|
+
const path_1 = __importDefault(require("path"));
|
|
6
13
|
/**
|
|
7
14
|
* Map of project names to their Crowdin ids. Can be retrieved by going to the
|
|
8
15
|
* project's dashboard in Crowdin and looking on the right side panel for ID:
|
|
@@ -12,23 +19,133 @@ exports.crowdinProjectIds = {
|
|
|
12
19
|
website: '698737',
|
|
13
20
|
app: '549537',
|
|
14
21
|
dmc: '663528',
|
|
22
|
+
emails: '929263',
|
|
15
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* Where a translated file lands, relative to the language folder. Every Waha
|
|
26
|
+
* project maps a language's Crowdin three-letter code onto its Waha id, which
|
|
27
|
+
* is why translations download straight into `crowdin/{wahaLanguageId}`.
|
|
28
|
+
*/
|
|
29
|
+
exports.CROWDIN_TRANSLATION_PATTERN = '%three_letters_code%/%original_file_name%';
|
|
30
|
+
/**
|
|
31
|
+
* Derives the Crowdin-relative path (what's shown in the dashboard, e.g.
|
|
32
|
+
* `eng/app_interface_text.json`) from an absolute filesystem path. Every
|
|
33
|
+
* Waha project keeps its Crowdin sources under a `crowdin/` directory, so
|
|
34
|
+
* that directory's name is the anchor: everything after the last `crowdin`
|
|
35
|
+
* segment is the path Crowdin knows about.
|
|
36
|
+
*
|
|
37
|
+
* This indirection exists because callers pass an absolute path rather than
|
|
38
|
+
* one relative to this file. `shared/` ships as a published npm package, so
|
|
39
|
+
* this file can end up executing from inside a consumer's `node_modules`,
|
|
40
|
+
* where a base path hardcoded relative to `__dirname` points nowhere useful.
|
|
41
|
+
*/
|
|
42
|
+
function crowdinRelativePath(absolutePath) {
|
|
43
|
+
const segments = absolutePath.split(path_1.default.sep);
|
|
44
|
+
const crowdinIndex = segments.lastIndexOf('crowdin');
|
|
45
|
+
if (crowdinIndex === -1) {
|
|
46
|
+
throw new Error(`Expected an absolute path under a "crowdin" directory, got "${absolutePath}".`);
|
|
47
|
+
}
|
|
48
|
+
return segments.slice(crowdinIndex + 1).join('/');
|
|
49
|
+
}
|
|
16
50
|
/**
|
|
17
51
|
* Downloads translations from Crowdin for a given project ID and source path.
|
|
18
52
|
*/
|
|
19
|
-
function downloadTranslations({ projectId, translationsFolder, token, }) {
|
|
53
|
+
function downloadTranslations({ projectId, translationsFolder, token, sourcePattern = '*.json', }) {
|
|
20
54
|
(0, node_child_process_1.spawnSync)([
|
|
21
|
-
'
|
|
55
|
+
'crowdin download translations',
|
|
22
56
|
`-i ${projectId}`,
|
|
23
|
-
`-s eng
|
|
57
|
+
`-s "eng/${sourcePattern}"`,
|
|
24
58
|
// Add Crowdin token present in .env file.
|
|
25
59
|
`-T ${token}`,
|
|
26
60
|
// Set the base path for which the other paths will be relative to.
|
|
27
61
|
`--base-path="${translationsFolder}"`,
|
|
28
62
|
// Where to download translations to relative to the base path.
|
|
29
|
-
|
|
63
|
+
`-t "/${exports.CROWDIN_TRANSLATION_PATTERN}"`,
|
|
30
64
|
].join(' '), {
|
|
31
65
|
shell: true,
|
|
32
66
|
stdio: 'inherit',
|
|
33
67
|
});
|
|
34
68
|
}
|
|
69
|
+
/** Uploads a source file to Crowdin, creating it or replacing its contents. */
|
|
70
|
+
async function uploadSource({ projectId, source, token, label, fileSettings, }) {
|
|
71
|
+
const client = new crowdin_api_client_1.default({ token });
|
|
72
|
+
const id = Number(projectId);
|
|
73
|
+
const relativePath = crowdinRelativePath(source);
|
|
74
|
+
const fileName = relativePath.split('/').pop();
|
|
75
|
+
const contents = fs_1.default.readFileSync(source, 'utf8');
|
|
76
|
+
const storage = await client.uploadStorageApi.addStorage(fileName, contents);
|
|
77
|
+
/*
|
|
78
|
+
* Replacing a file needs its numeric id, and the API has no by-path
|
|
79
|
+
* lookup, so this listing is how the id is obtained rather than a
|
|
80
|
+
* precaution. `filter` narrows it server-side; the path comparison still
|
|
81
|
+
* has to be exact because the filter matches on substrings.
|
|
82
|
+
*/
|
|
83
|
+
const files = await client.sourceFilesApi.listProjectFiles(id, {
|
|
84
|
+
filter: fileName,
|
|
85
|
+
limit: 500,
|
|
86
|
+
});
|
|
87
|
+
const existing = files.data.find((file) => file.data.path === `/${relativePath}`);
|
|
88
|
+
const exportOptions = {
|
|
89
|
+
exportPattern: `/${exports.CROWDIN_TRANSLATION_PATTERN}`,
|
|
90
|
+
};
|
|
91
|
+
const attachLabelIds = label ? [await labelId(client, id, label)] : undefined;
|
|
92
|
+
/*
|
|
93
|
+
* The two requests are built separately rather than sharing a spread. A
|
|
94
|
+
* file's parser `type` is fixed at creation and the replace endpoint
|
|
95
|
+
* rejects it outright, and spreading into a typed parameter skips
|
|
96
|
+
* TypeScript's excess property check — so a shared object hides the
|
|
97
|
+
* mistake until Crowdin returns "Field 'type' is unexpected".
|
|
98
|
+
*/
|
|
99
|
+
if (existing) {
|
|
100
|
+
const request = {
|
|
101
|
+
storageId: storage.data.id,
|
|
102
|
+
exportOptions,
|
|
103
|
+
// Keeps translations of revised strings but drops their approvals, so
|
|
104
|
+
// a reviewer looks again rather than stale copy staying green.
|
|
105
|
+
updateOption: 'keep_translations',
|
|
106
|
+
...(fileSettings?.importOptions && {
|
|
107
|
+
importOptions: fileSettings.importOptions,
|
|
108
|
+
}),
|
|
109
|
+
...(attachLabelIds && { attachLabelIds }),
|
|
110
|
+
};
|
|
111
|
+
await client.sourceFilesApi.updateOrRestoreFile(id, existing.data.id, request);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const request = {
|
|
115
|
+
storageId: storage.data.id,
|
|
116
|
+
name: fileName,
|
|
117
|
+
exportOptions,
|
|
118
|
+
...fileSettings,
|
|
119
|
+
...(attachLabelIds && { attachLabelIds }),
|
|
120
|
+
...(await directoryId(client, id, relativePath)),
|
|
121
|
+
};
|
|
122
|
+
await client.sourceFilesApi.createFile(id, request);
|
|
123
|
+
}
|
|
124
|
+
/** Resolves a label by title, creating it if Crowdin does not have it. */
|
|
125
|
+
async function labelId(client, projectId, title) {
|
|
126
|
+
const labels = await client.labelsApi.listLabels(projectId, { limit: 500 });
|
|
127
|
+
const existing = labels.data.find((label) => label.data.title === title);
|
|
128
|
+
if (existing)
|
|
129
|
+
return existing.data.id;
|
|
130
|
+
return (await client.labelsApi.addLabel(projectId, { title })).data.id;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Resolves the directory a new file belongs in, or nothing for projects that
|
|
134
|
+
* keep sources at the root.
|
|
135
|
+
*
|
|
136
|
+
* A missing directory is an error rather than something to create: a
|
|
137
|
+
* misspelled path that gets created silently uploads to a new file and
|
|
138
|
+
* orphans every translation attached to the real one.
|
|
139
|
+
*/
|
|
140
|
+
async function directoryId(client, projectId, relativePath) {
|
|
141
|
+
const segments = relativePath.split('/').slice(0, -1);
|
|
142
|
+
if (segments.length === 0)
|
|
143
|
+
return {};
|
|
144
|
+
const wanted = `/${segments.join('/')}`;
|
|
145
|
+
const directories = await client.sourceFilesApi.listProjectDirectories(projectId, { limit: 500 });
|
|
146
|
+
const match = directories.data.find((entry) => entry.data.path === wanted);
|
|
147
|
+
if (!match) {
|
|
148
|
+
throw new Error(`Crowdin project ${projectId} has no ${wanted} directory. Create it before uploading.`);
|
|
149
|
+
}
|
|
150
|
+
return { directoryId: match.data.id };
|
|
151
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
/** The two audiences a new signup can be enrolled in. */
|
|
3
|
+
export declare const DripSequenceId: z.ZodEnum<{
|
|
4
|
+
drip_believer: "drip_believer";
|
|
5
|
+
drip_seeker: "drip_seeker";
|
|
6
|
+
}>;
|
|
7
|
+
export type DripSequenceId = z.infer<typeof DripSequenceId>;
|
|
8
|
+
/** Languages the drip is provisioned for. */
|
|
9
|
+
export declare const DRIP_LANGUAGES: readonly ["eng", "ara", "swe"];
|
|
10
|
+
export declare const DripLanguageId: z.ZodEnum<{
|
|
11
|
+
eng: "eng";
|
|
12
|
+
ara: "ara";
|
|
13
|
+
swe: "swe";
|
|
14
|
+
}>;
|
|
15
|
+
export type DripLanguageId = z.infer<typeof DripLanguageId>;
|
|
16
|
+
export declare const SubscribeDripBody: z.ZodObject<{
|
|
17
|
+
sequence: z.ZodEnum<{
|
|
18
|
+
drip_believer: "drip_believer";
|
|
19
|
+
drip_seeker: "drip_seeker";
|
|
20
|
+
}>;
|
|
21
|
+
languageId: z.ZodEnum<{
|
|
22
|
+
eng: "eng";
|
|
23
|
+
ara: "ara";
|
|
24
|
+
swe: "swe";
|
|
25
|
+
}>;
|
|
26
|
+
firstName: z.ZodOptional<z.ZodString>;
|
|
27
|
+
}, z.core.$strip>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SubscribeDripBody = exports.DripLanguageId = exports.DRIP_LANGUAGES = exports.DripSequenceId = void 0;
|
|
7
|
+
const zod_1 = __importDefault(require("zod"));
|
|
8
|
+
/** The two audiences a new signup can be enrolled in. */
|
|
9
|
+
exports.DripSequenceId = zod_1.default.enum(['drip_believer', 'drip_seeker']);
|
|
10
|
+
/** Languages the drip is provisioned for. */
|
|
11
|
+
exports.DRIP_LANGUAGES = ['eng', 'ara', 'swe'];
|
|
12
|
+
exports.DripLanguageId = zod_1.default.enum(exports.DRIP_LANGUAGES);
|
|
13
|
+
exports.SubscribeDripBody = zod_1.default.object({
|
|
14
|
+
sequence: exports.DripSequenceId,
|
|
15
|
+
languageId: exports.DripLanguageId,
|
|
16
|
+
firstName: zod_1.default.string().optional(),
|
|
17
|
+
});
|
|
@@ -291,8 +291,8 @@ export declare const MicroLessonSubmission: z.ZodObject<{
|
|
|
291
291
|
timeSubmitted: z.ZodNumber;
|
|
292
292
|
platform: z.ZodEnum<{
|
|
293
293
|
web: "web";
|
|
294
|
-
ios: "ios";
|
|
295
294
|
android: "android";
|
|
295
|
+
ios: "ios";
|
|
296
296
|
}>;
|
|
297
297
|
}, z.core.$strip>;
|
|
298
298
|
export type MicroLessonSubmission = z.infer<typeof MicroLessonSubmission>;
|
package/dist/types/users.d.ts
CHANGED
|
@@ -59,8 +59,8 @@ export type UserReduxState = z.infer<typeof UserReduxState>;
|
|
|
59
59
|
export declare const WahaAppVersion: z.ZodString;
|
|
60
60
|
export declare const DevicePlatform: z.ZodEnum<{
|
|
61
61
|
web: "web";
|
|
62
|
-
ios: "ios";
|
|
63
62
|
android: "android";
|
|
63
|
+
ios: "ios";
|
|
64
64
|
macos: "macos";
|
|
65
65
|
windows: "windows";
|
|
66
66
|
}>;
|
|
@@ -88,8 +88,8 @@ export declare const DeviceInfo: z.ZodObject<{
|
|
|
88
88
|
}>>;
|
|
89
89
|
platform: z.ZodEnum<{
|
|
90
90
|
web: "web";
|
|
91
|
-
ios: "ios";
|
|
92
91
|
android: "android";
|
|
92
|
+
ios: "ios";
|
|
93
93
|
macos: "macos";
|
|
94
94
|
windows: "windows";
|
|
95
95
|
}>;
|
|
@@ -210,8 +210,8 @@ export declare const LegacyWahaUser: z.ZodObject<{
|
|
|
210
210
|
lastUpdate: z.ZodNumber;
|
|
211
211
|
platform: z.ZodEnum<{
|
|
212
212
|
web: "web";
|
|
213
|
-
ios: "ios";
|
|
214
213
|
android: "android";
|
|
214
|
+
ios: "ios";
|
|
215
215
|
macos: "macos";
|
|
216
216
|
windows: "windows";
|
|
217
217
|
}>;
|
|
@@ -296,8 +296,8 @@ export declare const LegacyWahaUser: z.ZodObject<{
|
|
|
296
296
|
timeSubmitted: z.ZodNumber;
|
|
297
297
|
platform: z.ZodEnum<{
|
|
298
298
|
web: "web";
|
|
299
|
-
ios: "ios";
|
|
300
299
|
android: "android";
|
|
300
|
+
ios: "ios";
|
|
301
301
|
}>;
|
|
302
302
|
}, z.core.$strip>>>;
|
|
303
303
|
obedienceScore: z.ZodOptional<z.ZodNumber>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "waha-shared",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.482",
|
|
4
4
|
"author": "Waha",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@types/signale": "^1.4.7",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
},
|
|
14
14
|
"description": "Shared assets for Waha's various apps",
|
|
15
15
|
"devDependencies": {
|
|
16
|
+
"@crowdin/crowdin-api-client": "^1.57.0",
|
|
16
17
|
"@types/react": "^19.3.0",
|
|
17
18
|
"copyfiles": "^2.4.1",
|
|
18
19
|
"react": "^19.3.0",
|