React-Admin <TranslateInput> how to get the translated label? - internationalization

following the docs [here][1] I created some en.js and fr.js file to translate the fields of my react-admin app
examples:
const fr = {
resources: {
categories: {
name: 'Catégorie |||| Catégories',
fields: {
code: 'N°',
trigram: 'Trigramme',
description: {
en: 'Description (Anglais)',
fr: 'Description (Français)',
cn: 'Description (Chinois)',
},
},
},
},
};
I have a similar file for English and Chinese with the description as follow
description: {
en: 'Description (English)',
fr: 'Description (French)',
cn: 'Description (Chinese)',
},
and
description: {
en: '类别的描述 (英文)',
fr: '类别的描述 (法文)',
cn: '类别的描述 (中文)',
},
this seems to work fine and I can use the TranslatableInputs as well
<TranslatableInputs locales={['en', 'fr', 'cn']}>
<TextInput source='description' />
</TranslatableInputs>
But, the label in the tab view doesn't seem to be applied (while in the list mode they are shown properly) using description.en for example so the link with the .js files is working fine I guess.
But as shown in the documentation with the Music example the label doesn't change when we switch tab (actually the same problem is show in the documentation's gif
the "name" label doesn't change to "nom"
[![enter image description here][2]][2]
any help to solve that? thanks a lot and thanks a lot to RA team for their wonderful work as well
Nico
[1]: https://marmelab.com/react-admin/TranslatableInputs.html
[2]: https://i.stack.imgur.com/16fWf.gif

That's a great question... And a current limitation of the TranslatableInput component.
The input label translation uses the global user locale, not the one of the selected tab. That would be a great feature to add to react-admin, and I invite you to open a feature request in the react-admin repository.
In the meantime, you should write your own TranslatableInput based on react-admin's, and wrap each tab content with <I18NContext.Provider> in which you force a different locale.
Something like (not tested):
export const TranslatableInputs = (props) => {
const {
className,
defaultLocale,
locales,
groupKey = '',
selector = <TranslatableInputsTabs groupKey={groupKey} />,
children,
variant,
margin,
} = props;
const context = useTranslatable({ defaultLocale, locales });
const i18nProvider = useI18nProvider();
return (
<Root className={className}>
<TranslatableContextProvider value={context}>
{selector}
{locales.map(locale => (
<I18nContext.Provider value={{...i18nProvider, getLocale: () => locale }}>
<TranslatableInputsTabContent
key={locale}
locale={locale}
groupKey={groupKey}
variant={variant}
margin={margin}
>
{children}
</TranslatableInputsTabContent>
</I18nContext.Provider>
))}
</TranslatableContextProvider>
</Root>
);
};

Related

How to wrap text in Polaris Index Table cell?

am using Polaris Index Table to display some data in my Shopify app. One of the cells in my table has a long string of text and I want to make it wrap so that it fits the size of the screen. Is there a way to do this in Polaris?
Here is my code:
import {IndexTable, Card, useIndexResourceState, Text} from '#shopify/polaris';
import React from 'react';
function SimpleIndexTableExample() {
const customers = [
{
id: '3411',
url: 'customers/341',
name: 'Mae Jemison long text here, very very long......',
location: 'Decatur, USA',
orders: 20,
amountSpent: '$2,400',
},
{
id: '2561',
url: 'customers/256',
name: 'Ellen Ochoa',
location: 'Los Angeles, USA',
orders: 30,
amountSpent: '$140',
},
];
const resourceName = {
singular: 'customer',
plural: 'customers',
};
const {selectedResources, allResourcesSelected, handleSelectionChange} =
useIndexResourceState(customers);
const rowMarkup = customers.map(
({id, name, location, orders, amountSpent}, index) => (
<IndexTable.Row
id={id}
key={id}
selected={selectedResources.includes(id)}
position={index}
>
<IndexTable.Cell>
<Text variant="bodyMd" fontWeight="bold" as="span">
{name}
</Text>
</IndexTable.Cell>
<IndexTable.Cell>{location}</IndexTable.Cell>
<IndexTable.Cell>{orders}</IndexTable.Cell>
<IndexTable.Cell>{amountSpent}</IndexTable.Cell>
</IndexTable.Row>
),
);
return (
<Card>
<IndexTable
resourceName={resourceName}
itemCount={customers.length}
selectedItemsCount={
allResourcesSelected ? 'All' : selectedResources.length
}
onSelectionChange={handleSelectionChange}
headings={[
{title: 'Name'},
{title: 'Location'},
{title: 'Order count'},
{title: 'Amount spent'},
]}
>
{rowMarkup}
</IndexTable>
</Card>
);
}
I've tried modifying the cells, styles, etc.
To make the text wrap in a cell in a Polaris IndexTable, you can apply the textWrap property to the Text component that you are using within the cell.
You may try this,
import {IndexTable, Card, useIndexResourceState, Text} from '#shopify/polaris';
import React from 'react';
function SimpleIndexTableExample() {
// ...
const rowMarkup = customers.map(
({id, name, location, orders, amountSpent}, index) => (
<IndexTable.Row
id={id}
key={id}
selected={selectedResources.includes(id)}
position={index}
>
<IndexTable.Cell>
<Text variant="bodyMd" fontWeight="bold" as="span" textWrap>
{name}
</Text>
</IndexTable.Cell>
<IndexTable.Cell>{location}</IndexTable.Cell>
<IndexTable.Cell>{orders}</IndexTable.Cell>
<IndexTable.Cell>{amountSpent}</IndexTable.Cell>
</IndexTable.Row>
),
);
// ...
}
I found a workaround for this – in my case there was a HTML representation of a text string available. Then I have used following construction in IndexTable.Row content:
<div dangerouslySetInnerHTML={{__html: myHTMLContent}} />
This allowed using line breaks and other HTML that can be formatted in a way you need. Of course I understand that this adds another problem of creating HTML string, but this is just a workaround.
P.S. that this method adds a risk of XSS attack so can recommend to use this only if you 100% understand the security side.

Trouble configuring CKEditor downcast for custom element

I have a custom Media Library which I need to integrate with CKEditor 5. I've managed to write a plugin for adding images and another for adding download links for documents, but I can't get the downcast conversion for the download links to work properly.
I am currently able to insert the following into the content of the CKEditor window:
<a class="downloadLink" data-file-id="3" download="pretty-file-name-for-download.pdf" href="actual_file_name.pdf">Download link text</a>
and when I save my content this gets written to the database - so far so good.
When I reload the content into the editor, it comes back formatted differently:
<a href="actual_file_name.pdf">
<a class="downloadLink" data-file-id="3" download="pretty-file-name-for-download.pdf" href="actual_file_name.pdf">Download link text</a>
</a>
There is now an additional anchor tag wrapping the original anchor tag.
My downcast and upcast converters look like this:
conversion.for('downcast').elementToElement( {
model: {
name: 'downloadLink',
attributes: ['fileId', 'fileUrl', 'fileDownloadName', 'title']
},
view: (modelElement, conversionApi) => {
const viewWriter = conversionApi.writer;
return viewWriter.createContainerElement(
'a',
{
'data-file-id': modelElement.getAttribute('fileId'),
'download': modelElement.getAttribute('fileDownloadName'),
'href': modelElement.getAttribute('fileUrl'),
'class': 'downloadLink'
},
viewWriter.createText(modelElement.getAttribute('title'))
);
}
} );
conversion.for('upcast').elementToElement( {
view: {
name: 'a',
classes: 'downloadLink'
},
model: (viewElement, conversionApi) => {
const modelWriter = conversionApi.writer;
return modelWriter.createElement(
'downloadLink',
{
fileId: viewElement.getAttribute('data-file-id'),
fileUrl: viewElement.getAttribute('href'),
fileDownloadName: viewElement.getAttribute('download'),
title: viewElement.getChild(0).data,
}
);
}
} );
If anyone has any suggestions about what I'm doing wrong I'd appreciate the help!

Mailchimp API Node - create campaign for list based on tags

I'm making an async api request with a firebase cloud function to create a campaign within mailchimp for a specific set of users from a list. I read in the documentation that this can be done with tags this way I can build my own structure. I'm building a donation system for a nonprofit and would like the tag to represent the name of a client who is currently being donated to.
Below is my firebase function. I'm stuck at the segment_opts object. I want to define a segment based on whether the list member has a tag equivalent my clients name.
The doc says segment_opts is "An object representing all segmentation options. This object should contain a saved_segment_id to use an existing segment, or you can create a new segment by including both match and conditions options.". I don't have any other segments set up so I figured I'd create a new one that specifies the tags to contain the client's name.
This post helped me get to this point. Stackoverflow post
I now see that condition is supposed to be a Segment Type but in the dropdown I don't see an option for Tags. Here is a link to the documentation reference. Reference
const response = await mailchimp.post('/campaigns', {
type: 'regular',
recipients: {
list_id: functions.config().mailchimp.test,
segment_opts: {
"match": "any",
"conditions": match: 'any',
conditions: [
{
condition_type: 'StaticSegment',
field: 'static_segment',
op: 'static_is',
value: ??? (Int),
},
],
}
},
});
For now I removed segment_opts and will settle on sending campaign to entire list until I figure out how to segment by tags. This version works and creates a campaign within my mailchimp account and from the UI I can see the segment options offered in the documentation but don't see an option to filter by tags
const response = await mailchimp.post('/campaigns', {
type: 'regular',
recipients: {
list_id: functions.config().mailchimp.test,
},
settings: {
subject_line: `${firstName} has been funded!`,
preview_text: `$${goal} has been raised for ${firstName}.`,
title: `${firstName} has been funded`,
from_name: 'Organization name',
reply_to: 'org_email#gmail.com',
},
});
Here is a screenshot of the dropdown options in Mailchimp dashboard.
This is what I have for my campaign segment options. Here I'm checking for two conditions. Is the SITE merge tag = the site variable I pass in, and also does the member belong to the tag/segment called tagName. However, I can't pass a tagName, only a tagId which I lookup beforehand.
'segment_opts':
{
'match': 'all',
'conditions': [
{
'condition_type': 'TextMerge',
'field': 'SITE',
'op': 'is',
'value': site
},
{
'condition_type': 'StaticSegment',
'field': 'static_segment',
'op': 'static_is',
'value': tagId
}
]
}
To get the tagId I use this Python function:
tagId, segments = self.getSegmentIdFromTagName(tagName)
This is the Python code to get the tagId from the tagName, which gets all the Segments/Tags from the system and then looks for the name you pass in:
def getSegmentIdFromTagName(self,reqTagName,segments=None):
audienceId = self.audienceId
reqId = None
if not segments:
segments = self.mcClient.lists.segments.all(list_id=audienceId,get_all=True)
for segment in segments['segments']:
segName = segment['name']
segId = segment['id']
if segName == reqTagName:
reqId = segId
break
return reqId,segments

How to label images in meteorJS application

I want to label images through your defined tags in meteor application.
I went through the following packages:
yogiben & meteor-simple-schema but was not able to find something concrete.
Additionally, meteor schema is using
MySchema = new SimpleSchema({
firstName: {
type: String,
label: function () {
return Session.get("lang") == "de"
? "Vorname" : "first name";
}
}
});
but I want the user to apply label dynamically.

CKEditor Turn Off Advanced Content Filter

I'm having difficulty deactivating the Advanced Content Filter (config.allowedContent = true; dosen't seem to work). I've tried everything that I've read on the forums, including clearing the cache, and making it an external file.
CKEditor 4.2.2 - allowedContent = true is not working
I've even added config.protectedSource.push lines, and they work to a point. The CKEditor still adds div tags and partially deletes other tags.
I'm creating a set of well designed templates for clients to use, so In the end I don't want CKEditor to touch my code at all. Here is what I have in the config.js. If anyone can see something I did wrong, or knows of a way to make it work, please help this somewhat stressed web guy.
Thanks,
Rusty
CKEDITOR.editorConfig = function( config ) {
config.toolbarGroups = [
{ name: 'document', groups: [ 'mode', 'document', 'doctools' ] },
{ name: 'clipboard', groups: [ 'clipboard', 'undo' ] },
{ name: 'editing', groups: [ 'find', 'selection', 'spellchecker' ] },
{ name: 'insert' },
{ name: 'links' },
{ name: 'others' },
'/',
{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
{ name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align' ] },
{ name: 'styles' },
{ name: 'colors' },
{ name: 'tools' },
{ name: 'about' }
];
// Define changes to default configuration here. For example:
// config.uiColor = '#AADC6E';
// misc options
config.allowedContent = true; // allowedContent doesn't work :-(
// Protected Source
config.protectedSource.push(/<section>[\s\S]*?<\/section>/gi); // allow <section></section>
config.protectedSource.push(/<span>[\s\S]*?<\/span>/gi); // allow <span></span>
config.protectedSource.push( /<link[\s\S]*?\>/g ); // allow <link> tag
config.protectedSource.push( /<!--[\s\S]*?\>/g ); // allow <comment> tag
config.protectedSource.push( /<br[\s\S]*?\/>/g ); // allow BR Tags
config.protectedSource.push(/<script>[\s\S]*?<\/script>/gi); // allow <script></script>
config.protectedSource.push(/<div>[\s\S]*?<\/div>/gi); // allow <div></div>
config.removeButtons = 'Anchor,Iframe';
config.format_tags = 'p;h1;h2;h3;h4;h5;h6'; // format button options
config.height = '500px'; // edit window height
config.skin = 'moono';
config.stylesSet = 'vam_styles:/templates/admin/-css/vam_styles.js'; // style button options
// Only add rules for p and span elements.
config.stylesheetParser_validSelectors = /\^(p|span\div)\.\w+/;
config.stylesheetParser_skipSelectors
};
I'm creating a set of well designed templates for clients to use, so In the end I don't want CKEditor to touch my code at all.
This is not possible. CKEditor is not a web site builder into which you can load any possible HTML. It is a rich text editor. So you should use it to edit the textual part of the website, not the whole layout.
For instance, if you had a layout with two columns and some header above them, it would be best if there were 3 editors - one for each column and one for the header. Of course, in this basic case CKEditor could be used to edit or 3 sections at once, but the more complex the layout the more important it is to use CKEditor correctly.
PS. It's CKEditor, not ckEditor.
Thanks for your reply.
I wasn't talking about site design templates, but page design templates. On the Full featured version of CKEditor there is a template button that we've been able to enhance. We now are able to let our clients choose several well designed page layouts that are responsive for different devises. It is very effective.
After trying everything I found the culprit that was causing the problem. I was using <br> instead of <br />. As soon as I switched the editor left my code alone.
Best Wishes!
Rusty

Resources