Skip to content

Commit

Permalink
feat(project): download translations
Browse files Browse the repository at this point in the history
  • Loading branch information
Giacomo Materozzi committed Mar 11, 2024
1 parent b8c21dc commit 5319ac4
Show file tree
Hide file tree
Showing 7 changed files with 397 additions and 19 deletions.
69 changes: 69 additions & 0 deletions components/app/project/dialogs/download.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import Link from "next/link"

import i18n from "@/lib/i18n"
import { cn } from "@/lib/utils"
import { buttonVariants } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"

import { DownloadFormat } from "../useTranslation"

type DownloadKeywordsDropdownMenuProps = {
id: string
download: (format: DownloadFormat) => void
}

export function DownloadKeywordsDropdownMenu(
props: DownloadKeywordsDropdownMenuProps
) {
const { id, download } = props
return (
<DropdownMenu>
<DropdownMenuTrigger className="mr-4">
<button
className={cn(
buttonVariants({ variant: "secondary" }),
"outline-none"
)}
>
<span>{i18n.t("Download")}</span>
</button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<div className="flex items-center justify-start gap-2 p-2">
<div className="flex flex-col space-y-1 leading-none">
<p className="truncate text-sm text-muted-foreground">
{i18n.t("Base url:")}
</p>
<p className="truncate text-sm text-muted-foreground">
{i18n.t("project.baseurl", { id })}
</p>
</div>
</div>
<DropdownMenuSeparator />
<DropdownMenuItem
asChild
className="hover:cursor-pointer flex"
onClick={() => {
download(DownloadFormat.json_files)
}}
>
<p>{i18n.t("Download .json files")}</p>
</DropdownMenuItem>
<DropdownMenuItem asChild className="hover:cursor-pointer">
<Link
target="_blank"
href="https://github.com/Matergi/Translo/pull/27/files"
>
{i18n.t("TS code")}
</Link>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)
}
7 changes: 6 additions & 1 deletion components/app/project/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { cn } from "@/lib/utils"
import { buttonVariants } from "@/components/ui/button"
import { Icons } from "@/components/icons"

import { DownloadKeywordsDropdownMenu } from "./dialogs/download"
import ImportKeywordsModal from "./dialogs/import-keywords"
import ProjectSettingsSlideOver from "./settings-slide-over"
import Table from "./table/table"
Expand All @@ -25,6 +26,8 @@ export interface EditorProps {
}

export function Editor(props: EditorProps) {
const { project } = props

const {
keywords,
isSaving,
Expand All @@ -45,6 +48,7 @@ export function Editor(props: EditorProps) {
addNewConstantTranslation,
checkIfKeyAlreadyExists,
importKeys,
download,
} = useTranslation(props)

const [isProjectSettingsOpened, openProjectSettings] =
Expand All @@ -65,6 +69,7 @@ export function Editor(props: EditorProps) {
</Link>
</div>
<div>
<DownloadKeywordsDropdownMenu id={project.id} download={download} />
<ImportKeywordsModal languages={languages} importKeys={importKeys} />
<button
onClick={() => openProjectSettings(true)}
Expand All @@ -85,7 +90,7 @@ export function Editor(props: EditorProps) {
id="title"
placeholder="Project name"
className="height-[288px] font-bold text-5xl bg-transparent w-full outline-none mb-10 mt-5"
value={title || props.project.title}
value={title || project.title}
onChange={(e) => setTitle(e.target.value)}
/>
<Table
Expand Down
46 changes: 33 additions & 13 deletions components/app/project/useTranslation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
ProjectSettings,
useI18nState,
} from "@/store/useI18nState"
import FileSaver from "file-saver"
import JSZip from "jszip"

import { EditorProps } from "."
import { toast } from "../../ui/use-toast"
Expand All @@ -32,6 +34,10 @@ export type Keyword = {
languagesAvailable: LanguagesAvailable[]
}

export enum DownloadFormat {
json_files = "json_files",
}

const useTranslation = (props: EditorProps) => {
const {
i18n,
Expand Down Expand Up @@ -132,21 +138,34 @@ const useTranslation = (props: EditorProps) => {
// return pauseAutocomplete ? "need to recharge ChatGPT..." : "Autogenerate"
// }, [isLoading, pauseAutocomplete])

// const downloadFile = useCallback(() => {
// const fileName = "i18n"
// const json = JSON.stringify(i18n, null, 2)
// const blob = new Blob([json], { type: "application/json" })
// const href = URL.createObjectURL(blob)
const downloadFiles = useCallback(() => {
const zip = new JSZip()

// const link = document.createElement("a")
// link.href = href
// link.download = fileName + ".json"
// document.body.appendChild(link)
// link.click()
i18n.languages.forEach((language: I18nLang) => {
zip.file(
`${language.short}.json`,
JSON.stringify(language.keywords, null, 4)
)
})

// document.body.removeChild(link)
// URL.revokeObjectURL(href)
// }, [i18n])
zip.generateAsync({ type: "blob" }).then(function (content) {
FileSaver.saveAs(
content,
`${props.project.title.replaceAll(" ", "-")}-translations.zip`
)
})
}, [i18n.languages, props.project.title])

const download = useCallback(
(format: DownloadFormat) => {
switch (format) {
case DownloadFormat.json_files:
downloadFiles()
break
}
},
[downloadFiles]
)

const editTranslation = useCallback(
(language: string, key: string, value: string) => {
Expand Down Expand Up @@ -226,6 +245,7 @@ const useTranslation = (props: EditorProps) => {
addNewConstantTranslation,
checkIfKeyAlreadyExists,
importKeys,
download,
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/i18n/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,5 @@ export default {

i18next.changeLanguage(lang)
},
t: (key: I18nKey) => i18next.t(key),
t: (key: I18nKey, vars: any = undefined) => i18next.t(key, vars).toString(),
}
5 changes: 5 additions & 0 deletions lib/i18n/languages/en.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
{
"Back": "Back",
"Base url:": "Base url:",
"Choose file": "Choose file",
"Continue": "Continue",
"Create": "Create",
"Create manage projects": "Create and manage translation projects.",
"dashboard.No project added.description": "You don't have any project yet. Start creating content.",
"Download": "Download",
"Download .json files": "Download .json files",
"Error parsing JSON": "Error parsing JSON",
"Female": "Female",
"Formal": "Formal",
Expand All @@ -21,6 +24,7 @@
"or paste the JSON": "or paste the JSON",
"Other": "Other",
"Project name": "Project name",
"project.baseurl": "https://translo.app/t/{{id}}",
"project.Import keywords.description": "Upload a .json file or paste the JSON into the designated field to add new keywords or to modify existing ones massively. We will guide you through the process. If there are keywords that already exist in the project, we will prompt you to select which ones you truly want to replace",
"Projects": "Projects",
"Save": "Save",
Expand All @@ -29,5 +33,6 @@
"Something went wrong": "Something went wrong",
"The content is not available": "The content is not available",
"To achieve a well-done translation, we need to provide context to the AI": "To achieve a well-done translation, we need to provide context to the AI",
"TS code": "TS code",
"Upload .json file": "Upload .json file"
}
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,12 @@
"crypto-js": "^4.2.0",
"date-fns": "^2.29.3",
"dotenv-cli": "^7.3.0",
"file-saver": "^2.0.5",
"flowbite": "^2.3.0",
"framer-motion": "^11.0.5",
"i18next": "^23.10.0",
"i18next-resources-to-backend": "^1.2.0",
"jszip": "^3.10.1",
"lucide-react": "^0.92.0",
"next": "13.3.2-canary.13",
"next-auth": "4.22.1",
Expand Down Expand Up @@ -142,6 +144,7 @@
"tailwindcss": "^3.3.1",
"ts-node": "^10.9.2",
"typescript": "4.7.4",
"typescript-eslint": "^7.1.1",
"unist-util-visit": "^4.1.2"
},
"config": {
Expand Down
Loading

0 comments on commit 5319ac4

Please sign in to comment.