chore: add translation
This commit is contained in:
parent
6dae766f77
commit
5483adf926
32
README.md
32
README.md
|
@ -62,6 +62,37 @@ TODO
|
|||
| activeCategoryColor | string | "#005b96" | no | Change active category item color |
|
||||
| categoryContainerColor | string | "#e3dbcd" | no | Change category container color |
|
||||
| onCategoryChangeFailed | function | warn(info) | no | Callback on category change failed (info: {index, highestMeasuredFrameIndex, averageItemLength}) |
|
||||
| translation | CategoryTranslation | en | no | Translation object *see translation section* |
|
||||
## Internationalization
|
||||
### Pre-defined
|
||||
Due to the limited translation possibilities, we only provide a few pre-defined translations into the following languages:
|
||||
* `en` - English
|
||||
* `pl` - Polish
|
||||
|
||||
First import lang and use it as `translation` prop.
|
||||
```ts
|
||||
import { pl } from '{package-name}';
|
||||
|
||||
// ...
|
||||
|
||||
translation={pl}
|
||||
```
|
||||
### Own
|
||||
There is possibility to pass own translation to library with the prop called `translation` like this
|
||||
```ts
|
||||
translation={{
|
||||
smileys_emotion: 'Smileys & Emotion',
|
||||
people_body: 'People & Body',
|
||||
animals_nature: 'Animals & Nature',
|
||||
food_drink: 'Food & Drink',
|
||||
travel_places: 'Travel & Places',
|
||||
activities: 'Activities',
|
||||
objects: 'Objects',
|
||||
symbols: 'Symbols',
|
||||
flags: 'Flags',
|
||||
}}
|
||||
```
|
||||
*If you have written a translation into your language, we strongly encourage you to create a Pull Request and add your language to the package, following the example of other langs.*
|
||||
## License
|
||||
**MIT**
|
||||
|
||||
|
@ -69,4 +100,3 @@ TODO
|
|||
## TODO
|
||||
categories => Specify displayed categories
|
||||
|
||||
language => Use translation
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as React from 'react';
|
||||
|
||||
import { StyleSheet, Text, SafeAreaView, TouchableOpacity } from 'react-native';
|
||||
import EmojiPicker from 'react-native-emoji-keyboard';
|
||||
import EmojiPicker, { pl } from 'react-native-emoji-keyboard';
|
||||
|
||||
export default function App() {
|
||||
const [result, setResult] = React.useState<string>();
|
||||
|
@ -26,6 +26,7 @@ export default function App() {
|
|||
onEmojiSelected={handlePick}
|
||||
open={isModalOpen}
|
||||
onClose={() => setIsModalOpen(false)}
|
||||
translation={pl}
|
||||
/>
|
||||
|
||||
{/* //////////////////////////////////////////// */}
|
||||
|
|
|
@ -8,7 +8,10 @@ for (const [key, value] of Object.entries(json)) {
|
|||
name: emoji.name,
|
||||
slug: emoji.slug,
|
||||
}));
|
||||
newArray.push({ title: key, data: newData });
|
||||
newArray.push({
|
||||
title: key.replace(' & ', '_').replace(' ', '_').toLocaleLowerCase(),
|
||||
data: newData,
|
||||
});
|
||||
}
|
||||
|
||||
fs.writeFile(
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
defaultKeyboardContext,
|
||||
defaultKeyboardValues,
|
||||
} from './KeyboardProvider';
|
||||
import type { EmojiType } from './types';
|
||||
import type { CategoryTranslation, EmojiType } from './types';
|
||||
|
||||
export type KeyboardProps = {
|
||||
open: boolean;
|
||||
|
@ -27,6 +27,7 @@ export type KeyboardProps = {
|
|||
highestMeasuredFrameIndex: number;
|
||||
averageItemLength: number;
|
||||
}) => void;
|
||||
translation?: CategoryTranslation;
|
||||
};
|
||||
export type ContextValues = {
|
||||
activeCategoryIndex: number;
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
ContextValues,
|
||||
KeyboardContext,
|
||||
} from './KeyboardContext';
|
||||
import en from './translation/en';
|
||||
import type { EmojiType } from './types';
|
||||
|
||||
type ProviderProps = KeyboardProps & {
|
||||
|
@ -30,6 +31,7 @@ export const defaultKeyboardContext: Required<KeyboardProps> = {
|
|||
onCategoryChangeFailed: (info) => {
|
||||
console.warn(info);
|
||||
},
|
||||
translation: en,
|
||||
};
|
||||
|
||||
export const defaultKeyboardValues: ContextValues = {
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,7 +1,7 @@
|
|||
import * as React from 'react';
|
||||
|
||||
import { StyleSheet, View, Text, FlatList } from 'react-native';
|
||||
import type { EmojisByCategory, EmojiType } from 'src/types';
|
||||
import type { EmojisByCategory, EmojiType } from '../types';
|
||||
import { SingleEmoji } from './SingleEmoji';
|
||||
import { KeyboardContext } from '../KeyboardContext';
|
||||
|
||||
|
@ -19,23 +19,30 @@ export const EmojiCategory = ({
|
|||
}: {
|
||||
item: EmojisByCategory;
|
||||
}) => {
|
||||
const { onEmojiSelected, emojiSize, ...ctx } =
|
||||
React.useContext(KeyboardContext);
|
||||
const {
|
||||
onEmojiSelected,
|
||||
emojiSize,
|
||||
numberOfColumns,
|
||||
width,
|
||||
hideHeader,
|
||||
headerStyles,
|
||||
translation,
|
||||
} = React.useContext(KeyboardContext);
|
||||
|
||||
const [empty, setEmpty] = React.useState<EmojiType[]>([]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (data.length % ctx.numberOfColumns) {
|
||||
if (data.length % numberOfColumns) {
|
||||
const fillWithEmpty = new Array(
|
||||
ctx.numberOfColumns - (data.length % ctx.numberOfColumns)
|
||||
numberOfColumns - (data.length % numberOfColumns)
|
||||
).fill(emptyEmoji);
|
||||
setEmpty(fillWithEmpty);
|
||||
}
|
||||
}, [ctx.numberOfColumns, data]);
|
||||
}, [numberOfColumns, data]);
|
||||
|
||||
const getItemLayout = (_: EmojiType[] | null | undefined, index: number) => ({
|
||||
length: emojiSize ? emojiSize : 0,
|
||||
offset: emojiSize * Math.ceil(index / ctx.numberOfColumns),
|
||||
offset: emojiSize * Math.ceil(index / numberOfColumns),
|
||||
index,
|
||||
});
|
||||
|
||||
|
@ -51,14 +58,16 @@ export const EmojiCategory = ({
|
|||
);
|
||||
|
||||
return (
|
||||
<View style={[styles.container, { width: ctx.width }]}>
|
||||
{!ctx.hideHeader && (
|
||||
<Text style={[styles.sectionTitle, ctx.headerStyles]}>{title}</Text>
|
||||
<View style={[styles.container, { width: width }]}>
|
||||
{!hideHeader && (
|
||||
<Text style={[styles.sectionTitle, headerStyles]}>
|
||||
{translation[title]}
|
||||
</Text>
|
||||
)}
|
||||
<FlatList
|
||||
data={[...data, ...empty]}
|
||||
keyExtractor={(emoji) => emoji.name}
|
||||
numColumns={ctx.numberOfColumns}
|
||||
numColumns={numberOfColumns}
|
||||
renderItem={renderItem}
|
||||
removeClippedSubviews={true}
|
||||
getItemLayout={getItemLayout}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import { EmojiKeyboard } from './EmojiKeyboard';
|
||||
import { EmojiPicker } from './EmojiPicker';
|
||||
import { KeyboardProvider } from './KeyboardProvider';
|
||||
import en from './translation/en';
|
||||
import pl from './translation/pl';
|
||||
|
||||
export { EmojiKeyboard, KeyboardProvider };
|
||||
export { en, pl };
|
||||
|
||||
export default EmojiPicker;
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import type { CategoryTranslation } from '../types';
|
||||
|
||||
export const en: CategoryTranslation = {
|
||||
smileys_emotion: 'Smileys & Emotion',
|
||||
people_body: 'People & Body',
|
||||
animals_nature: 'Animals & Nature',
|
||||
food_drink: 'Food & Drink',
|
||||
travel_places: 'Travel & Places',
|
||||
activities: 'Activities',
|
||||
objects: 'Objects',
|
||||
symbols: 'Symbols',
|
||||
flags: 'Flags',
|
||||
};
|
||||
export default en;
|
|
@ -0,0 +1,14 @@
|
|||
import type { CategoryTranslation } from '../types';
|
||||
|
||||
const pl: CategoryTranslation = {
|
||||
smileys_emotion: 'Buźki i Emocje',
|
||||
people_body: 'Ludzie',
|
||||
animals_nature: 'Zwierzęta i przyroda',
|
||||
food_drink: 'Jedzenie i napoje',
|
||||
travel_places: 'Podróże i miejsca',
|
||||
activities: 'Aktywność',
|
||||
objects: 'Przedmioty',
|
||||
symbols: 'Symbole',
|
||||
flags: 'Flagi',
|
||||
};
|
||||
export default pl;
|
58
src/types.ts
58
src/types.ts
|
@ -5,26 +5,26 @@ export type EmojiType = {
|
|||
};
|
||||
|
||||
export type CategoryTypes =
|
||||
| 'Smileys & Emotion'
|
||||
| 'People & Body'
|
||||
| 'Animals & Nature'
|
||||
| 'Food & Drink'
|
||||
| 'Travel & Places'
|
||||
| 'Activities'
|
||||
| 'Objects'
|
||||
| 'Symbols'
|
||||
| 'Flags';
|
||||
| 'smileys_emotion'
|
||||
| 'people_body'
|
||||
| 'animals_nature'
|
||||
| 'food_drink'
|
||||
| 'travel_places'
|
||||
| 'activities'
|
||||
| 'objects'
|
||||
| 'symbols'
|
||||
| 'flags';
|
||||
|
||||
export const CATEGORIES: CategoryTypes[] = [
|
||||
'Smileys & Emotion',
|
||||
'People & Body',
|
||||
'Animals & Nature',
|
||||
'Food & Drink',
|
||||
'Travel & Places',
|
||||
'Activities',
|
||||
'Objects',
|
||||
'Symbols',
|
||||
'Flags',
|
||||
'smileys_emotion',
|
||||
'people_body',
|
||||
'animals_nature',
|
||||
'food_drink',
|
||||
'travel_places',
|
||||
'activities',
|
||||
'objects',
|
||||
'symbols',
|
||||
'flags',
|
||||
];
|
||||
|
||||
export type CategoryNavigationItem = {
|
||||
|
@ -32,16 +32,20 @@ export type CategoryNavigationItem = {
|
|||
category: CategoryTypes;
|
||||
};
|
||||
|
||||
export type CategoryTranslation = {
|
||||
[key in CategoryTypes]: string;
|
||||
};
|
||||
|
||||
export const CATEGORIES_NAVIGATION: CategoryNavigationItem[] = [
|
||||
{ icon: 'Smile', category: 'Smileys & Emotion' },
|
||||
{ icon: 'Users', category: 'People & Body' },
|
||||
{ icon: 'Trees', category: 'Animals & Nature' },
|
||||
{ icon: 'Pizza', category: 'Food & Drink' },
|
||||
{ icon: 'Plane', category: 'Travel & Places' },
|
||||
{ icon: 'Football', category: 'Activities' },
|
||||
{ icon: 'Lightbulb', category: 'Objects' },
|
||||
{ icon: 'Ban', category: 'Symbols' },
|
||||
{ icon: 'Flag', category: 'Flags' },
|
||||
{ icon: 'Smile', category: 'smileys_emotion' },
|
||||
{ icon: 'Users', category: 'people_body' },
|
||||
{ icon: 'Trees', category: 'animals_nature' },
|
||||
{ icon: 'Pizza', category: 'food_drink' },
|
||||
{ icon: 'Plane', category: 'travel_places' },
|
||||
{ icon: 'Football', category: 'activities' },
|
||||
{ icon: 'Lightbulb', category: 'objects' },
|
||||
{ icon: 'Ban', category: 'symbols' },
|
||||
{ icon: 'Flag', category: 'flags' },
|
||||
];
|
||||
|
||||
export type EmojisByCategory = {
|
||||
|
|
Loading…
Reference in New Issue