Skip to content

Commit

Permalink
working with single file
Browse files Browse the repository at this point in the history
  • Loading branch information
rawand-faraidun committed Nov 27, 2023
1 parent 562c912 commit 7d5c93f
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 68 deletions.
2 changes: 1 addition & 1 deletion src/client/src/components/sections/NamespaceCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const NamespaceCard = ({ ns, ...actionProps }: Props) => {
<CardHeader>
<CardTitle>{namespace}</CardTitle>
<CardDescription>
{config?.localesPath}/{'{locale}'}/{ns}
{config?.useSingleFile ? `${config?.localesPath}/{locale}.json` : `${config?.localesPath}/{locale}/${ns}`}
</CardDescription>
</CardHeader>
</Card>
Expand Down
2 changes: 1 addition & 1 deletion src/client/src/pages/Namespace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default function Page() {
<div>
<h1 className="text-4xl font-bold">{namespace}</h1>
<p className="text-muted-foreground">
{config?.localesPath}/{'{locale}'}/{ns}
{config?.useSingleFile ? `${config?.localesPath}/{locale}.json` : `${config?.localesPath}/{locale}/${ns}`}
</p>
</div>

Expand Down
144 changes: 97 additions & 47 deletions src/server/controllers/key.controller.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,78 @@
import { writeFileSync } from 'fs'
import { type RequestHandler } from 'express'
import _ from 'lodash'
import { getNamespaceJson, getPath, isNamespaceExists } from '@lib/functions'
import { getFileJson, getNamespaceJson, getPath, isNamespaceExists } from '@lib/functions'
import { clear, isAssignable, unflatten } from '@lib/object'
import type { DynamicObject } from '@lib/types'
import { config, otherLocales } from '@lib/utils'
import validate, { S } from '@lib/validation/validate'

/**
* key body props
*/
type Key = {
key: string
value: string
translations: Record<string, string>
}

/**
* create key
*/
export const createKey: RequestHandler = (req, res) => {
try {
const { ns } = req.params
validate(S.namespace, ns)
const filename = ns!
const name = ns!
validate(S.key, req.body, { makeOptional: ['oldKey'] })
const { key, value, translations } = req.body as { key: string; value: string; translations: Record<string, string> }
const { key, value, translations } = req.body as Key

// returning key result
let result: DynamicObject = { key, value, translations: [] }

// checking namespace existance
if (!isNamespaceExists(filename)) throw new Error('Namespace does not exist')
if (!isNamespaceExists(name)) throw new Error('Namespace does not exist')

// namespace values
const defaultJson = getNamespaceJson(config.defaultLocale, filename)
const defaultJson = getNamespaceJson(config.defaultLocale, name)

// checking if the key exists or assignable
if (_.has(defaultJson, key)) throw new Error('Key already exists')
let assignable = isAssignable(defaultJson, key)
if (assignable != true) throw new Error(`Point '${assignable}' already exists`)

// adding to default language
// // adding to default language
const defaultUnflattened = unflatten({ [key]: value })
writeFileSync(getPath(config.defaultLocale, filename), JSON.stringify(_.merge(defaultJson, defaultUnflattened)))

// adding to other languages
otherLocales.forEach(locale => {
const json = getNamespaceJson(locale, filename)
const unflattened = unflatten({ [key]: translations[locale] || value })
writeFileSync(getPath(locale, filename), JSON.stringify(_.merge(json, unflattened)))
result.translations.push({ [locale]: value })
})
if (config.useSingleFile) {
const file = getFileJson(`${config.defaultLocale}.json`)
file[name] = _.merge(defaultJson, defaultUnflattened)
writeFileSync(getPath(`${config.defaultLocale}.json`), JSON.stringify(file))
} else {
writeFileSync(getPath(config.defaultLocale, name), JSON.stringify(_.merge(defaultJson, defaultUnflattened)))
}

// // adding to other languages
if (config.useSingleFile) {
otherLocales.forEach(locale => {
const file = getFileJson(`${locale}.json`)
const json = getNamespaceJson(locale, name)
const unflattened = unflatten({ [key]: translations[locale] || value })
file[name] = _.merge(json, unflattened)
writeFileSync(getPath(`${locale}.json`), JSON.stringify(file))
result.translations.push({ [locale]: value })
})
} else {
otherLocales.forEach(locale => {
const json = getNamespaceJson(locale, name)
const unflattened = unflatten({ [key]: translations[locale] || value })
writeFileSync(getPath(locale, name), JSON.stringify(_.merge(json, unflattened)))
result.translations.push({ [locale]: value })
})
}

res.status(200).json({
data: {
namespace: filename,
namespace: name,
key: result
},
success: true,
Expand All @@ -64,29 +90,24 @@ export const updateKey: RequestHandler = (req, res) => {
try {
const { ns } = req.params
validate(S.namespace, ns)
const filename = ns!
const name = ns!
validate(S.key, req.body)
const { oldKey, key, value, translations } = req.body as {
oldKey: string
key: string
value: string
translations: Record<string, string>
}
const { oldKey, key, value, translations } = req.body as Key & { oldKey: string }

// returning key result
let result: DynamicObject = { key, value, translations: [] }

// checking namespace existance
if (!isNamespaceExists(filename)) throw new Error('Namespace does not exist')
if (!isNamespaceExists(name)) throw new Error('Namespace does not exist')

// namespace values
const defaultJson = getNamespaceJson(config.defaultLocale, filename)
const defaultJson = getNamespaceJson(config.defaultLocale, name)

// checking if the edited key exists
if (!_.has(defaultJson, oldKey)) throw new Error('Key does not exists')

// removing old key
let newJson = defaultJson
let newJson = _.cloneDeep(defaultJson)
_.unset(newJson, oldKey)
newJson = clear(newJson)

Expand All @@ -98,23 +119,42 @@ export const updateKey: RequestHandler = (req, res) => {
if (assignable != true) throw new Error(`Point '${assignable}' already exists`)
}

// adding to default language
// modifing to default language
const defaultUnflattened = unflatten({ [key]: value })
writeFileSync(getPath(config.defaultLocale, filename), JSON.stringify(_.merge(newJson, defaultUnflattened)))

// adding to other languages
otherLocales.forEach(locale => {
let json = getNamespaceJson(locale, filename)
_.unset(json, oldKey)
json = clear(json)
const unflattened = unflatten({ [key]: translations[locale] || value })
writeFileSync(getPath(locale, filename), JSON.stringify(_.merge(json, unflattened)))
result.translations.push({ [locale]: value })
})
if (config.useSingleFile) {
const file = getFileJson(`${config.defaultLocale}.json`)
file[name] = _.merge(newJson, defaultUnflattened)
writeFileSync(getPath(`${config.defaultLocale}.json`), JSON.stringify(file))
} else {
writeFileSync(getPath(config.defaultLocale, name), JSON.stringify(_.merge(newJson, defaultUnflattened)))
}

// modifing to other languages
if (config.useSingleFile) {
otherLocales.forEach(locale => {
const file = getFileJson(`${locale}.json`)
let json = getNamespaceJson(locale, name)
const unflattened = unflatten({ [key]: translations[locale] || value })
_.unset(json, oldKey)
json = clear(json)
file[name] = _.merge(json, unflattened)
writeFileSync(getPath(`${locale}.json`), JSON.stringify(file))
result.translations.push({ [locale]: value })
})
} else {
otherLocales.forEach(locale => {
let json = getNamespaceJson(locale, name)
_.unset(json, oldKey)
json = clear(json)
const unflattened = unflatten({ [key]: translations[locale] || value })
writeFileSync(getPath(locale, name), JSON.stringify(_.merge(json, unflattened)))
result.translations.push({ [locale]: value })
})
}

res.status(200).json({
data: {
namespace: filename,
namespace: name,
key: result
},
success: true,
Expand All @@ -132,22 +172,32 @@ export const deleteKeys: RequestHandler = (req, res) => {
try {
const { ns } = req.params
validate(S.namespace, ns)
const filename = ns!
const name = ns!
const { keys } = req.body as { keys: string[] }
validate(S.keysStringArray, keys)

// checking namespace existance
if (!isNamespaceExists(filename)) throw new Error('Namespace does not exist')
if (!isNamespaceExists(name)) throw new Error('Namespace does not exist')

// deleting keys
config.locales.forEach(locale => {
let json = getNamespaceJson(locale, filename)
keys.forEach(k => _.unset(json, k))
writeFileSync(getPath(locale, filename), JSON.stringify(clear(json)))
})
if (config.useSingleFile) {
config.locales.forEach(locale => {
const file = getFileJson(`${locale}.json`)
let json = getNamespaceJson(locale, name)
keys.forEach(k => _.unset(json, k))
file[name] = clear(json)
writeFileSync(getPath(`${locale}.json`), JSON.stringify(file))
})
} else {
config.locales.forEach(locale => {
let json = getNamespaceJson(locale, name)
keys.forEach(k => _.unset(json, k))
writeFileSync(getPath(locale, name), JSON.stringify(clear(json)))
})
}

res.status(200).json({
data: { namespace: filename, keys: keys },
data: { namespace: name, keys: keys },
success: true,
message: 'Keys deleted successfully'
})
Expand Down
67 changes: 48 additions & 19 deletions src/server/controllers/namespace.controller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { renameSync, rmSync, writeFileSync } from 'fs'
import { type RequestHandler } from 'express'
import { getNamespaces as getConfigNamespaces, getNamespaceJson, getPath, isNamespaceExists } from '@lib/functions'
import {
getNamespaces as getConfigNamespaces,
getFileJson,
getNamespaceJson,
getPath,
isNamespaceExists
} from '@lib/functions'
import { flatten } from '@lib/object'
import type { DynamicObject } from '@lib/types'
import { config, otherLocales } from '@lib/utils'
Expand Down Expand Up @@ -34,10 +40,10 @@ export const getNamespace: RequestHandler = (req, res) => {
try {
const { ns } = req.params
validate(S.namespace, ns)
const filename = ns!
const name = ns!

// checking namespace existance
if (!isNamespaceExists(filename)) throw new Error('Namespace does not exist')
if (!isNamespaceExists(name)) throw new Error('Namespace does not exist')

// each namespace values
const values: DynamicObject = {}
Expand All @@ -48,7 +54,7 @@ export const getNamespace: RequestHandler = (req, res) => {

// reading namespace values from each locale
config.locales.forEach(locale => {
const value = getNamespaceJson(locale, filename)
let value = getNamespaceJson(locale, name)
values[locale] = value
flattened[locale] = flatten(value)
})
Expand All @@ -63,7 +69,7 @@ export const getNamespace: RequestHandler = (req, res) => {

res.status(200).json({
data: {
namespace: filename,
namespace: name,
values,
flatten: flattened,
flattenValues
Expand All @@ -83,16 +89,22 @@ export const createNamespace: RequestHandler = (req, res) => {
try {
const { namespace } = req.body
validate(S.namespace, namespace)
const filename = `${namespace}.json`
const name = config.useSingleFile ? namespace! : `${namespace}.json`

// checking namespace existance
if (isNamespaceExists(filename)) throw new Error('Namespace already exists')
if (isNamespaceExists(name)) throw new Error('Namespace already exists')

// creating the namespace
config.locales.forEach(locale => writeFileSync(getPath(locale, filename), '{}'))
if (config.useSingleFile) {
config.locales.forEach(locale =>
writeFileSync(getPath(`${locale}.json`), JSON.stringify({ ...getFileJson(`${locale}.json`), [namespace]: {} }))
)
} else {
config.locales.forEach(locale => writeFileSync(getPath(locale, name), '{}'))
}

res.status(200).json({
data: { namespace: filename },
data: { namespace: name },
success: true,
message: 'Namespaces created successfully'
})
Expand All @@ -110,20 +122,29 @@ export const updateNamespace: RequestHandler = (req, res) => {
validate(S.namespace, ns)
const { namespace } = req.body
validate(S.namespace, namespace)
const oldFilename = ns!
const filename = `${namespace}.json`
const oldName = ns!
const name = config.useSingleFile ? namespace! : `${namespace}.json`

// checking namespace existance
if (!isNamespaceExists(oldFilename)) throw new Error('Namespace does not exist')
if (!isNamespaceExists(oldName)) throw new Error('Namespace does not exist')

// checking new namespace existance
if (isNamespaceExists(filename)) throw new Error('Namespace already exists')
if (isNamespaceExists(name)) throw new Error('Namespace already exists')

// renaming the namespace
config.locales.forEach(locale => renameSync(getPath(locale, oldFilename), getPath(locale, filename)))
if (config.useSingleFile) {
config.locales.forEach(locale => {
const file = getFileJson(`${locale}.json`)
file[namespace] = file[oldName]
delete file[oldName]
writeFileSync(getPath(`${locale}.json`), JSON.stringify(file))
})
} else {
config.locales.forEach(locale => renameSync(getPath(locale, oldName), getPath(locale, name)))
}

res.status(200).json({
data: { namespace: filename, oldNamespace: oldFilename },
data: { namespace: name, oldNamespace: oldName },
success: true,
message: 'Namespaces updated successfully'
})
Expand All @@ -139,16 +160,24 @@ export const deleteNamespace: RequestHandler = (req, res) => {
try {
const { ns } = req.params
validate(S.namespace, ns)
const filename = ns!
const name = ns!

// checking namespace existance
if (!isNamespaceExists(filename)) throw new Error('Namespace does not exist')
if (!isNamespaceExists(name)) throw new Error('Namespace does not exist')

// creating the namespace
config.locales.forEach(locale => rmSync(getPath(locale, filename)))
if (config.useSingleFile) {
config.locales.forEach(locale => {
const file = getFileJson(`${locale}.json`)
delete file[name]
writeFileSync(getPath(`${locale}.json`), JSON.stringify(file))
})
} else {
config.locales.forEach(locale => rmSync(getPath(locale, name)))
}

res.status(200).json({
data: { namespace: filename },
data: { namespace: name },
success: true,
message: 'Namespaces deleted successfully'
})
Expand Down

0 comments on commit 7d5c93f

Please sign in to comment.