Skip to content

Commit

Permalink
i18n: swap verbatim strings to i18n refs
Browse files Browse the repository at this point in the history
  • Loading branch information
jamiebrynes7 committed Aug 13, 2024
1 parent 04c2160 commit 6d65ef3
Show file tree
Hide file tree
Showing 21 changed files with 194 additions and 122 deletions.
19 changes: 13 additions & 6 deletions plugin/src/commands/addTask.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
import type { Translations } from "@/i18n/translation";
import { MarkdownView, Notice, TFile } from "obsidian";
import type { MakeCommand } from ".";
import type TodoistPlugin from "..";
import type { TaskCreationOptions } from "../ui/createTaskModal";

export const addTask: MakeCommand = (plugin: TodoistPlugin) => {
export const addTask: MakeCommand = (plugin: TodoistPlugin, i18n: Translations["commands"]) => {
return {
name: "Add task",
name: i18n.addTask,
callback: makeCallback(plugin),
};
};

export const addTaskWithPageInContent: MakeCommand = (plugin: TodoistPlugin) => {
export const addTaskWithPageInContent: MakeCommand = (
plugin: TodoistPlugin,
i18n: Translations["commands"],
) => {
return {
id: "add-task-page-content",
name: "Add task with current page in task content",
name: i18n.addTaskPageContent,
callback: makeCallback(plugin, { appendLinkToContent: true }),
};
};

export const addTaskWithPageInDescription: MakeCommand = (plugin: TodoistPlugin) => {
export const addTaskWithPageInDescription: MakeCommand = (
plugin: TodoistPlugin,
i18n: Translations["commands"],
) => {
return {
id: "add-task-page-description",
name: "Add task with current page in task description",
name: i18n.addTaskPageDescription,
callback: makeCallback(plugin, { appendLinkToDescription: true }),
};
};
Expand Down
17 changes: 12 additions & 5 deletions plugin/src/commands/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { t } from "@/i18n";
import type { Translations } from "@/i18n/translation";
import { type Command as ObsidianCommand } from "obsidian";
import type TodoistPlugin from "..";
import debug from "../log";
import { addTask, addTaskWithPageInContent, addTaskWithPageInDescription } from "./addTask";

export type MakeCommand = (plugin: TodoistPlugin) => Omit<ObsidianCommand, "id">;
export type MakeCommand = (
plugin: TodoistPlugin,
i18n: Translations["commands"],
) => Omit<ObsidianCommand, "id">;

const syncCommand: MakeCommand = (plugin: TodoistPlugin) => {
const syncCommand: MakeCommand = (plugin: TodoistPlugin, i18n: Translations["commands"]) => {
return {
name: "Sync with Todoist",
name: i18n.sync,
callback: async () => {
debug("Syncing with Todoist API");
plugin.services.todoist.sync();
Expand All @@ -25,12 +30,14 @@ const commands = {
type CommandId = keyof typeof commands;

export const registerCommands = (plugin: TodoistPlugin) => {
const i18n = t().commands;
for (const [id, make] of Object.entries(commands)) {
plugin.addCommand({ id, ...make(plugin) });
plugin.addCommand({ id, ...make(plugin, i18n) });
}
};

export const fireCommand = <K extends CommandId>(id: K, plugin: TodoistPlugin) => {
const i18n = t().commands;
const make = commands[id];
make(plugin).callback?.();
make(plugin, i18n).callback?.();
};
7 changes: 5 additions & 2 deletions plugin/src/token.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { t } from "@/i18n";
import { TodoistApiClient } from "./api";
import { ObsidianFetcher } from "./api/fetcher";

Expand All @@ -9,8 +10,10 @@ export namespace TokenValidation {
| { kind: "success" };

export const validate = async (token: string, tester: TokenTester): Promise<Result> => {
const i18n = t().tokenValidation;

if (token.length === 0) {
return { kind: "error", message: "API token must not be empty" };
return { kind: "error", message: i18n.emptyTokenError };
}

const [isValid, _] = await Promise.all([
Expand All @@ -21,7 +24,7 @@ export namespace TokenValidation {
if (!isValid) {
return {
kind: "error",
message: "Oops! Todoist does not recognize this token. Please double check and try again!",
message: i18n.invalidTokenError,
};
}

Expand Down
36 changes: 22 additions & 14 deletions plugin/src/ui/createTaskModal/DueDateSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { t } from "@/i18n";
import {
CalendarDate,
DateFormatter,
Expand Down Expand Up @@ -94,22 +95,24 @@ export const DueDateSelector: React.FC<Props> = ({ selected, setSelected }) => {
}
};

const i18n = t().createTaskModal.dateSelector;

return (
<DialogTrigger>
<Button className="due-date-selector" aria-label="Set due Date">
<Button className="due-date-selector" aria-label={i18n.buttonLabel}>
<ObsidianIcon size={16} id="calendar" />
{label}
</Button>
<Popover maxHeight={600}>
<Dialog className="task-option-dialog task-date-menu" aria-label="Due date selector">
<Dialog className="task-option-dialog task-date-menu" aria-label={i18n.dialogLabel}>
{({ close }) => (
<>
<Menu
onAction={(key: Key) => {
selectedDateSuggestion(key);
close();
}}
aria-label="Due date suggestions"
aria-label={i18n.suggestionsLabel}
>
<Section>
{suggestions.map((props) => (
Expand All @@ -119,7 +122,7 @@ export const DueDateSelector: React.FC<Props> = ({ selected, setSelected }) => {
</Menu>
<hr />
<Calendar
aria-label="Task date"
aria-label={i18n.datePickerLabel}
className="date-picker"
value={selected?.date ?? null}
onChange={(date) => {
Expand Down Expand Up @@ -164,18 +167,20 @@ export const DueDateSelector: React.FC<Props> = ({ selected, setSelected }) => {
};

const getLabel = (selected: DueDate | undefined) => {
const i18n = t().createTaskModal.dateSelector;

if (selected === undefined) {
return "Due date";
return i18n.emptyDate;
}

const date = selected.date;
const dayPart = (() => {
if (isToday(date, getLocalTimeZone())) {
return "Today";
return i18n.today;
}

if (today(getLocalTimeZone()).add({ days: 1 }).compare(date) === 0) {
return "Tomorrow";
return i18n.tomorrow;
}

return formatter.format(date.toDate(getLocalTimeZone()));
Expand Down Expand Up @@ -220,30 +225,32 @@ const DateSuggestion: React.FC<DateSuggestionProps> = ({ id, icon, label, target
};

const getSuggestions = (): DateSuggestionProps[] => {
const i18n = t().createTaskModal.dateSelector;

const startOfNextWeek = endOfWeek(today(getLocalTimeZone()), "en-US").add({ days: 1 });
const suggestions = [
{
id: "today",
icon: "calendar",
label: "Today",
label: i18n.today,
target: today(getLocalTimeZone()),
},
{
id: "tomorrow",
icon: "sun",
label: "Tomorrow",
label: i18n.tomorrow,
target: today(getLocalTimeZone()).add({ days: 1 }),
},
{
id: "next-week",
icon: "calendar-clock",
label: "Next week",
label: i18n.nextWeek,
target: startOfNextWeek,
},
{
id: "no-date",
icon: "ban",
label: "No date",
label: i18n.noDate,
target: undefined,
},
];
Expand All @@ -258,29 +265,30 @@ type TimeDialogProps = {

const TimeDialog: React.FC<TimeDialogProps> = ({ selectedTime, setTime }) => {
const [taskTime, setTaskTime] = useState(selectedTime);
const i18n = t().createTaskModal.dateSelector.timeDialog;

return (
<Dialog className="task-option-dialog task-time-menu" aria-label="Time selector">
{({ close }) => (
<>
<TimeField className="task-time-picker" value={taskTime ?? null} onChange={setTaskTime}>
<Label className="task-time-picker-label">Time</Label>
<Label className="task-time-picker-label">{i18n.timeLabel}</Label>
<DateInput className="task-time-picker-input">
{(segment) => (
<DateSegment className="task-time-picker-input-segment" segment={segment} />
)}
</DateInput>
</TimeField>
<div className="task-time-controls">
<Button onPress={close}>Cancel</Button>
<Button onPress={close}>{i18n.cancelButtonLabel}</Button>
<Button
className="mod-cta"
onPress={() => {
close();
setTime(taskTime);
}}
>
Save
{i18n.saveButtonLabel}
</Button>
</div>
</>
Expand Down
8 changes: 6 additions & 2 deletions plugin/src/ui/createTaskModal/LabelSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { t } from "@/i18n";
import { PluginContext } from "@/ui/context";
import React, { useMemo } from "react";
import { Button, DialogTrigger, ListBox, ListBoxItem, type Selection } from "react-aria-components";
Expand Down Expand Up @@ -28,15 +29,18 @@ export const LabelSelector: React.FC<Props> = ({ selected, setSelected }) => {
setSelected(options.filter((l) => selection.has(l.id)));
};

const i18n = t().createTaskModal.labelSelector;

return (
<DialogTrigger>
<Button className="label-selector" aria-label="Set labels">
<Button className="label-selector" aria-label={i18n.buttonLabel}>
<ObsidianIcon size={16} id="tag" />
{i18n.buttonText(selected.length)}
Labels ({selected.length})
</Button>
<Popover>
<ListBox
aria-label="Label options"
aria-label={i18n.labelOptionsLabel}
selectionMode="multiple"
className="task-option-dialog task-label-menu"
selectedKeys={selectedKeys}
Expand Down
25 changes: 16 additions & 9 deletions plugin/src/ui/createTaskModal/PrioritySelector.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { t } from "@/i18n";
import type { Translations } from "@/i18n/translation";
import classNames from "classnames";
import React from "react";
import { Button, type Key, Label, Menu, MenuItem, MenuTrigger } from "react-aria-components";
Expand All @@ -23,22 +25,24 @@ export const PrioritySelector: React.FC<Props> = ({ selected, setSelected }) =>
setSelected(key as Priority);
};

const label = getLabel(selected);
const i18n = t().createTaskModal.prioritySelector;

const label = getLabel(selected, i18n);
return (
<MenuTrigger>
<Button className="priority-selector" aria-label="Set priority">
<Button className="priority-selector" aria-label={i18n.buttonLabel}>
<ObsidianIcon size={16} id="flag" />
{label}
</Button>
<Popover>
<Menu
className="task-option-dialog task-priority-menu"
autoFocus="first"
aria-label="Task priority options"
aria-label={i18n.optionsLabel}
onAction={onSelected}
>
{options.map((priority) => {
const label = getLabel(priority);
const label = getLabel(priority, i18n);
const isSelected = priority === selected;
const className = classNames("priority-option", { "is-selected": isSelected });
return (
Expand All @@ -53,15 +57,18 @@ export const PrioritySelector: React.FC<Props> = ({ selected, setSelected }) =>
);
};

const getLabel = (priority: Priority): string => {
const getLabel = (
priority: Priority,
i18n: Translations["createTaskModal"]["prioritySelector"],
): string => {
switch (priority) {
case 1:
return "Priority 4";
return i18n.p4;
case 2:
return "Priority 3";
return i18n.p3;
case 3:
return "Priority 2";
return i18n.p2;
case 4:
return "Priority 1";
return i18n.p1;
}
};
20 changes: 10 additions & 10 deletions plugin/src/ui/createTaskModal/ProjectSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { t } from "@/i18n";
import { PluginContext } from "@/ui/context";
import { Platform } from "obsidian";
import React, { useMemo, useState } from "react";
Expand Down Expand Up @@ -57,14 +58,16 @@ export const ProjectSelector: React.FC<Props> = ({ selected, setSelected }) => {
setSelected({ projectId: id });
};

const i18n = t().createTaskModal.projectSelector;

return (
<DialogTrigger>
<Button className="project-selector" aria-label="Set project">
<Button className="project-selector" aria-label={i18n.buttonLabel}>
<ButtonLabel {...selected} />
<ObsidianIcon size={12} id="chevron-down" />
</Button>
<Popover>
<Dialog className="task-option-dialog task-project-menu" aria-label="Project selector">
<Dialog className="task-option-dialog task-project-menu" aria-label={i18n.selectorLabel}>
{({ close }) => (
<>
{!Platform.isMobile && (
Expand All @@ -74,7 +77,7 @@ export const ProjectSelector: React.FC<Props> = ({ selected, setSelected }) => {
</>
)}
<ListBox
aria-label="Project options"
aria-label={i18n.optionsLabel}
selectionMode="single"
onAction={(key) => {
onSelect(key);
Expand Down Expand Up @@ -103,14 +106,11 @@ const SearchFilter: React.FC<SearchFilterProps> = ({ filter, setFilter }) => {
setFilter(changeEv.target.value.toLowerCase());
};

const i18n = t().createTaskModal.projectSelector.search;

return (
<SearchField aria-label="Filter projects" className="search-filter-container">
<Input
value={filter}
onChange={onChange}
placeholder="Type a project name"
autoFocus={true}
/>
<SearchField aria-label={i18n.label} className="search-filter-container">
<Input value={filter} onChange={onChange} placeholder={i18n.placeholder} autoFocus={true} />
</SearchField>
);
};
Expand Down
2 changes: 1 addition & 1 deletion plugin/src/ui/createTaskModal/TaskContentInput.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import classNames from "classnames";
import React from "react";
import { TextArea, TextField } from "react-aria-components";
import { TextField } from "react-aria-components";
import TextareaAutosize from "react-textarea-autosize";

type Props = {
Expand Down
Loading

0 comments on commit 6d65ef3

Please sign in to comment.