Custom Localization

Custom localization provides the ability to customize SpreadJS with a specific language. Users can also get the current or specified culture language resources and translate to their custom resources.

Users need to define the localization object with the schema, or get the current working or specified culture resources with GC.Spread.Common.CultureManager.getResources(cultureName?: string). Then add to the CultureManager and switch to the defined culture. The worksheet displays different properties with the defined words. For example: Or modify resources based on specified culture resources. Hint: If some of the statements are not set, Spread will display English (if set to an empty string “”, it will not display anything).. The arguments is use {0}, {1}, … for display (e.g.: "Invalid {0}: {1} (must be between {2} and {3}).", "Height: {0} pixels"). Custom localization does not support fromJSON/toJSON, so a user will need to add it every time it is needed. The namespace ("common", "Sheets", "Filter") in the sample is optional, but "Functions" and "TableFunctions" are required. The following is also a valid format:
import * as React from 'react'; import { createRoot } from 'react-dom/client'; import './styles.css'; import { AppFunc } from './app-func'; // import { App } from './app-class'; // 1. Functional Component sample createRoot(document.getElementById('app')).render(<AppFunc />); // 2. Class Component sample // createRoot(document.getElementById('app')).render(<App />);
import * as React from 'react'; import GC from '@mescius/spread-sheets'; import '@mescius/spread-sheets-resources-zh'; import { SpreadSheets, Worksheet } from '@mescius/spread-sheets-react'; let spread = null; export function AppFunc() { const [languageOption, setLanguageOption] = React.useState({ language: "", l_description: "Define English for all worksheet properties as the base and default culture." }); const initSpread = (currSpread) => { spread = currSpread; let sheet = spread.getActiveSheet(); spread.suspendPaint(); spread.options.showScrollTip = 3; spread.options.showResizeTip = 3; let table = sheet.tables.addFromDataSource("table1", 0, 0, source, GC.Spread.Sheets.Tables.TableThemes.medium9) table.showFooter(true); table.showHeader(true); table.highlightFirstColumn(true); table.setColumnFormula(2, "=SUM(C2:C10)"); table.setColumnFormula(3, "=SUM(D2:D10)"); table.setColumnValue(0, "Total"); sheet.setColumnWidth(0, 130); sheet.setColumnWidth(4, 100); GC.Spread.Common.CultureManager.addCultureInfo("de", null, de); let zhResources = GC.Spread.Common.CultureManager.getResources("zh-cn"); zhResources.Sheets.Tip_Column = zh_tw.Sheet.Tip_Column; zhResources.Sheets.Tip_Height = zh_tw.Sheet.Tip_Height; zhResources.Sheets.Tip_Row = zh_tw.Sheet.Tip_Row; zhResources.Sheets.Tip_Width = zh_tw.Sheet.Tip_Width; zhResources.Sheets.NewTab = zh_tw.Sheet.NewTab; zhResources.StatusBar = zh_tw.StatusBar; zhResources.CalcEngine.Fbx_Summary = zh_tw.CalcEngine.Fbx_Summary; zhResources.Functions.SUM = zh_tw.Functions.SUM; zhResources.Functions.NOW = zh_tw.Functions.NOW; zhResources.Functions.IF = zh_tw.Functions.IF; GC.Spread.Common.CultureManager.addCultureInfo("zh_tw", null, zhResources); GC.Spread.Common.CultureManager.addCultureInfo("fr", null, fr); GC.Spread.Common.CultureManager.addCultureInfo("ha_ha", null, ha_ha); let statusBar = new GC.Spread.Sheets.StatusBar.StatusBar(document.getElementById('statusBar')); statusBar.bind(spread); spread.resumePaint(); } const changeCultureName = (e) => { let culture = e.target.value; GC.Spread.Common.CultureManager.culture(culture); const newOption = { l_description: langDescription[culture] }; if (culture === "en") { newOption.language = ""; } else if (culture === "zh_tw") { newOption.language = JSON.stringify(GC.Spread.Common.CultureManager.getResources("zh_tw"), null, 2); } else { newOption.language = JSON.stringify(window[culture], null, 2); } setLanguageOption(newOption); } return <div class="sample-tutorial"> <div class="sample-container"> <div class="sample-spreadsheets"> <SpreadSheets workbookInitialized={initSpread}> <Worksheet> </Worksheet> </SpreadSheets> </div> <div id="statusBar"></div> </div> <div className="sample-options"> <div className="options-container"> Switch Culture: <select id="CultureSelect" onChange={changeCultureName}> <option value="en">en</option> <option value="zh_tw">zh-tw</option> <option value="fr">fr</option> <option value="de">de</option> <option value="ha_ha">Ha-Ha</option> </select> <p>{ languageOption.l_description }</p> <textarea id="language" cols={85} rows={40} style={{ maxWidth: '98%', height: '500px' }} readOnly="readonly" defaultValue={""} value={languageOption.language} /> <div className="sample-options"> <div className="options-container"> </div> </div> </div> </div> </div>; }
import * as React from 'react'; import GC from '@mescius/spread-sheets'; import '@mescius/spread-sheets-resources-zh'; import { SpreadSheets, Worksheet } from '@mescius/spread-sheets-react'; const Component = React.Component; export class App extends Component { constructor(props) { super(props); this.spread = null; this.state = { language: "", l_description: "Define English for all worksheet properties as the base and default culture." }; } render() { return <div class="sample-tutorial"> <div class="sample-container"> <div class="sample-spreadsheets"> <SpreadSheets workbookInitialized={spread => this.initSpread(spread)}> <Worksheet> </Worksheet> </SpreadSheets> </div> <div id="statusBar"></div> </div> <div className="sample-options"> <div className="options-container"> Switch Culture: <select id="CultureSelect" onChange={e=>this.changeCultureName(e)}> <option value="en">en</option> <option value="zh_tw">zh-tw</option> <option value="fr">fr</option> <option value="de">de</option> <option value="ha_ha">Ha-Ha</option> </select> <p>{ this.state.l_description }</p> <textarea id="language" cols={85} rows={40} style={{ maxWidth: '98%', height: '500px' }} readOnly="readonly" defaultValue={""} value={this.state.language} /> <div className="sample-options"> <div className="options-container"> </div> </div> </div> </div> </div>; } initSpread(spread) { this.spread = spread; let sheet = spread.getActiveSheet(); spread.suspendPaint(); spread.options.showScrollTip = 3; spread.options.showResizeTip = 3; let table = sheet.tables.addFromDataSource("table1", 0, 0, source, GC.Spread.Sheets.Tables.TableThemes.medium9) table.showFooter(true); table.showHeader(true); table.highlightFirstColumn(true); table.setColumnFormula(2, "=SUM(C2:C10)"); table.setColumnFormula(3, "=SUM(D2:D10)"); table.setColumnValue(0, "Total"); sheet.setColumnWidth(0, 130); sheet.setColumnWidth(4, 100); GC.Spread.Common.CultureManager.addCultureInfo("de", null, de); let zhResources = GC.Spread.Common.CultureManager.getResources("zh-cn"); zhResources.Sheets.Tip_Column = zh_tw.Sheet.Tip_Column; zhResources.Sheets.Tip_Height = zh_tw.Sheet.Tip_Height; zhResources.Sheets.Tip_Row = zh_tw.Sheet.Tip_Row; zhResources.Sheets.Tip_Width = zh_tw.Sheet.Tip_Width; zhResources.Sheets.NewTab = zh_tw.Sheet.NewTab; zhResources.StatusBar = zh_tw.StatusBar; zhResources.CalcEngine.Fbx_Summary = zh_tw.CalcEngine.Fbx_Summary; zhResources.Functions.SUM = zh_tw.Functions.SUM; zhResources.Functions.NOW = zh_tw.Functions.NOW; zhResources.Functions.IF = zh_tw.Functions.IF; GC.Spread.Common.CultureManager.addCultureInfo("zh_tw", null, zhResources); GC.Spread.Common.CultureManager.addCultureInfo("fr", null, fr); GC.Spread.Common.CultureManager.addCultureInfo("ha_ha", null, ha_ha); let statusBar = new GC.Spread.Sheets.StatusBar.StatusBar(document.getElementById('statusBar')); statusBar.bind(spread); spread.resumePaint(); } changeCultureName(e) { let culture = e.target.value; GC.Spread.Common.CultureManager.culture(culture); this.setState({l_description: langDescription[culture]}); if (culture === "en") { this.setState({language: ""}); } else if (culture === "zh_tw") { this.setState({language: JSON.stringify(GC.Spread.Common.CultureManager.getResources("zh_tw"), null, 2)}); } else { this.setState({language: JSON.stringify(window[culture], null, 2)}); } } }
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/react/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <script src="$DEMOROOT$/spread/source/data/customLocalization.js" type="text/javascript"></script> <!-- SystemJS --> <script src="$DEMOROOT$/en/react/node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('$DEMOROOT$/en/lib/react/license.js').then(function () { System.import('./src/app'); }); </script> </head> <body> <div id="app"></div> </body> </html>
* { -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } .sample-options { float: right; height: 100%; } .options-toggle { display: none; } .sample-tutorial { position: relative; height: 100%; overflow: hidden; } .sample-container { width: calc(100% - 280px); height: 100%; float: left; } .sample-spreadsheets { width: 100%; height: calc(100% - 25px); overflow: hidden; } #statusBar { bottom: 0; height: 25px; width: 100%; position: relative; } .options-container { float: right; width: 280px; padding: 12px; box-sizing: border-box; background: #fbfbfb; overflow: auto; } .option-row { font-size: 14px; padding: 5px; margin-top: 10px; } label { display: block; margin-bottom: 6px; } input { padding: 4px 6px; box-sizing: border-box; width: 100%; } input[type=button] { margin-top: 6px; display: block; } .summary { background-color: #e6e6fa; padding: 3px; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; } #app { height: 100%; }
(function (global) { System.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true, react: true }, meta: { '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { '@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js', '@mescius/spread-sheets-resources-zh': 'npm:@mescius/spread-sheets-resources-zh/index.js', '@mescius/spread-sheets-react': 'npm:@mescius/spread-sheets-react/index.js', '@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js', 'react': 'npm:react/cjs/react.production.js', 'react-dom': 'npm:react-dom/cjs/react-dom.production.js', 'react-dom/client': 'npm:react-dom/cjs/react-dom-client.production.js', 'scheduler': 'npm:scheduler/cjs/scheduler.production.js', 'css': 'npm:systemjs-plugin-css/css.js', 'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js', 'systemjs-babel-build':'npm:systemjs-plugin-babel/systemjs-babel-browser.js' }, // packages tells the System loader how to load when no filename and/or no extension packages: { src: { defaultExtension: 'jsx' }, "node_modules": { defaultExtension: 'js' }, } }); })(this);