From c4f65681a160c4e62d947ba22b81246ac0b2c6a4 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Tue, 20 Feb 2018 14:11:19 -0800 Subject: Add translation infra and replace english text with calls to translate --- packages/website/ts/components/footer.tsx | 180 ++++++++++---------- packages/website/ts/components/top_bar/top_bar.tsx | 67 +++++--- packages/website/ts/pages/landing/landing.tsx | 181 +++++++++------------ packages/website/ts/translations/english.ts | 78 +++++++++ packages/website/ts/types.ts | 71 ++++++++ packages/website/ts/utils/translate.ts | 54 ++++++ 6 files changed, 412 insertions(+), 219 deletions(-) create mode 100644 packages/website/ts/translations/english.ts create mode 100644 packages/website/ts/utils/translate.ts diff --git a/packages/website/ts/components/footer.tsx b/packages/website/ts/components/footer.tsx index a0f1a0c96..a5bddc874 100644 --- a/packages/website/ts/components/footer.tsx +++ b/packages/website/ts/components/footer.tsx @@ -1,9 +1,10 @@ import * as _ from 'lodash'; import * as React from 'react'; import { Link } from 'react-router-dom'; -import { WebsitePaths } from 'ts/types'; +import { Deco, Key, WebsitePaths } from 'ts/types'; import { colors } from 'ts/utils/colors'; import { constants } from 'ts/utils/constants'; +import { Translate } from 'ts/utils/translate'; interface MenuItemsBySection { [sectionName: string]: FooterMenuItem[]; @@ -15,86 +16,8 @@ interface FooterMenuItem { isExternal?: boolean; } -enum Sections { - Documentation = 'Documentation', - Community = 'Community', - Organization = 'Organization', -} - const ICON_DIMENSION = 16; -const menuItemsBySection: MenuItemsBySection = { - Documentation: [ - { - title: '0x.js', - path: WebsitePaths.ZeroExJs, - }, - { - title: '0x Smart Contracts', - path: WebsitePaths.SmartContracts, - }, - { - title: '0x Connect', - path: WebsitePaths.Connect, - }, - { - title: 'Whitepaper', - path: WebsitePaths.Whitepaper, - isExternal: true, - }, - { - title: 'Wiki', - path: WebsitePaths.Wiki, - }, - { - title: 'FAQ', - path: WebsitePaths.FAQ, - }, - ], - Community: [ - { - title: 'Rocket.chat', - isExternal: true, - path: constants.URL_ZEROEX_CHAT, - }, - { - title: 'Blog', - isExternal: true, - path: constants.URL_BLOG, - }, - { - title: 'Twitter', - isExternal: true, - path: constants.URL_TWITTER, - }, - { - title: 'Reddit', - isExternal: true, - path: constants.URL_REDDIT, - }, - { - title: 'Forum', - isExternal: true, - path: constants.URL_DISCOURSE_FORUM, - }, - ], - Organization: [ - { - title: 'About', - isExternal: false, - path: WebsitePaths.About, - }, - { - title: 'Careers', - isExternal: true, - path: constants.URL_ANGELLIST, - }, - { - title: 'Contact', - isExternal: true, - path: 'mailto:team@0xproject.com', - }, - ], -}; + const linkStyle = { color: colors.white, cursor: 'pointer', @@ -108,12 +31,90 @@ const titleToIcon: { [title: string]: string } = { Forum: 'discourse.png', }; -export interface FooterProps {} +export interface FooterProps { + translate?: Translate; +} interface FooterState {} export class Footer extends React.Component { + public static defaultProps: Partial = { + translate: new Translate(), + }; public render() { + const menuItemsBySection: MenuItemsBySection = { + [Key.Documentation]: [ + { + title: '0x.js', + path: WebsitePaths.ZeroExJs, + }, + { + title: this.props.translate.get(Key.SmartContracts, Deco.Cap), + path: WebsitePaths.SmartContracts, + }, + { + title: this.props.translate.get(Key.Connect, Deco.Cap), + path: WebsitePaths.Connect, + }, + { + title: this.props.translate.get(Key.Whitepaper, Deco.Cap), + path: WebsitePaths.Whitepaper, + isExternal: true, + }, + { + title: this.props.translate.get(Key.Wiki, Deco.Cap), + path: WebsitePaths.Wiki, + }, + { + title: this.props.translate.get(Key.FAQ, Deco.Cap), + path: WebsitePaths.FAQ, + }, + ], + [Key.Community]: [ + { + title: this.props.translate.get(Key.RocketChat, Deco.Cap), + isExternal: true, + path: constants.URL_ZEROEX_CHAT, + }, + { + title: this.props.translate.get(Key.Blog, Deco.Cap), + isExternal: true, + path: constants.URL_BLOG, + }, + { + title: 'Twitter', + isExternal: true, + path: constants.URL_TWITTER, + }, + { + title: 'Reddit', + isExternal: true, + path: constants.URL_REDDIT, + }, + { + title: this.props.translate.get(Key.Forum, Deco.Cap), + isExternal: true, + path: constants.URL_DISCOURSE_FORUM, + }, + ], + [Key.Organization]: [ + { + title: this.props.translate.get(Key.About, Deco.Cap), + isExternal: false, + path: WebsitePaths.About, + }, + { + title: this.props.translate.get(Key.Careers, Deco.Cap), + isExternal: true, + path: constants.URL_ANGELLIST, + }, + { + title: this.props.translate.get(Key.Contact, Deco.Cap), + isExternal: true, + path: 'mailto:team@0xproject.com', + }, + ], + }; return (
@@ -137,20 +138,20 @@ export class Footer extends React.Component {
- {this._renderHeader(Sections.Documentation)} - {_.map(menuItemsBySection[Sections.Documentation], this._renderMenuItem.bind(this))} + {this._renderHeader(Key.Documentation)} + {_.map(menuItemsBySection[Key.Documentation], this._renderMenuItem.bind(this))}
- {this._renderHeader(Sections.Community)} - {_.map(menuItemsBySection[Sections.Community], this._renderMenuItem.bind(this))} + {this._renderHeader(Key.Community)} + {_.map(menuItemsBySection[Key.Community], this._renderMenuItem.bind(this))}
- {this._renderHeader(Sections.Organization)} - {_.map(menuItemsBySection[Sections.Organization], this._renderMenuItem.bind(this))} + {this._renderHeader(Key.Organization)} + {_.map(menuItemsBySection[Key.Organization], this._renderMenuItem.bind(this))}
@@ -195,9 +196,8 @@ export class Footer extends React.Component {
); } - private _renderHeader(title: string) { + private _renderHeader(key: Key) { const headerStyle = { - textTransform: 'uppercase', color: colors.grey400, letterSpacing: 2, fontFamily: 'Roboto Mono', @@ -205,7 +205,7 @@ export class Footer extends React.Component { }; return (
- {title} + {this.props.translate.get(key, Deco.Upper)}
); } diff --git a/packages/website/ts/components/top_bar/top_bar.tsx b/packages/website/ts/components/top_bar/top_bar.tsx index a412007f2..15bfe2a39 100644 --- a/packages/website/ts/components/top_bar/top_bar.tsx +++ b/packages/website/ts/components/top_bar/top_bar.tsx @@ -14,9 +14,10 @@ import { Identicon } from 'ts/components/ui/identicon'; import { DocsInfo } from 'ts/pages/documentation/docs_info'; import { NestedSidebarMenu } from 'ts/pages/shared/nested_sidebar_menu'; import { Dispatcher } from 'ts/redux/dispatcher'; -import { DocsMenu, MenuSubsectionsBySection, ProviderType, Styles, WebsitePaths } from 'ts/types'; +import { Deco, DocsMenu, Key, MenuSubsectionsBySection, ProviderType, Styles, WebsitePaths } from 'ts/types'; import { colors } from 'ts/utils/colors'; import { constants } from 'ts/utils/constants'; +import { Translate } from 'ts/utils/translate'; interface TopBarProps { userAddress?: string; @@ -36,6 +37,7 @@ interface TopBarProps { docsInfo?: DocsInfo; style?: React.CSSProperties; isNightVersion?: boolean; + translate?: Translate; } interface TopBarState { @@ -79,6 +81,7 @@ export class TopBar extends React.Component { shouldFullWidth: false, style: {}, isNightVersion: false, + translate: new Translate(), }; constructor(props: TopBarProps) { super(props); @@ -95,10 +98,16 @@ export class TopBar extends React.Component { , - + , - + , { className="text-decoration-none" href={constants.URL_STANDARD_RELAYER_API_GITHUB} > - + , { className="text-decoration-none" href={`${WebsitePaths.Whitepaper}`} > - + , ]; const bottomBorderStyle = this._shouldDisplayBottomBar() ? styles.bottomBar : {}; @@ -165,28 +180,28 @@ export class TopBar extends React.Component { style={styles.menuItem} /> { {this._renderDocsMenu()} {this._renderWiki()}
- Website + {this.props.translate.get(Key.Website, Deco.Cap)}
- Home + {this.props.translate.get(Key.Home, Deco.Cap)} - Wiki + {this.props.translate.get(Key.Wiki, Deco.Cap)} {!this._isViewing0xjsDocs() && ( - 0x.js Docs + 0x.js {this.props.translate.get(Key.Docs, Deco.Cap)} )} {!this._isViewingConnectDocs() && ( - 0x Connect Docs + + {this.props.translate.get(Key.Connect, Deco.Cap)}{' '} + {this.props.translate.get(Key.Docs, Deco.Cap)} + )} {!this._isViewingSmartContractsDocs() && ( - Smart Contract Docs + + {this.props.translate.get(Key.SmartContract, Deco.Cap)}{' '} + {this.props.translate.get(Key.Docs, Deco.Cap)} + )} {!this._isViewingPortal() && ( - Portal DApp + + {this.props.translate.get(Key.PortalDApp, Deco.CapWords)} + )} - Whitepaper + {this.props.translate.get(Key.Whitepaper, Deco.Cap)} - About + {this.props.translate.get(Key.About, Deco.Cap)} - Blog + {this.props.translate.get(Key.Blog, Deco.Cap)} - FAQ + {this.props.translate.get(Key.FAQ, Deco.Cap)}
@@ -313,7 +336,7 @@ export class TopBar extends React.Component { @@ -328,7 +351,7 @@ export class TopBar extends React.Component { return (
- Portal DApp + {this.props.translate.get(Key.PortalDApp, Deco.CapWords)}
diff --git a/packages/website/ts/pages/landing/landing.tsx b/packages/website/ts/pages/landing/landing.tsx index d4c934459..76ea2e1bd 100644 --- a/packages/website/ts/pages/landing/landing.tsx +++ b/packages/website/ts/pages/landing/landing.tsx @@ -5,9 +5,10 @@ import DocumentTitle = require('react-document-title'); import { Link } from 'react-router-dom'; import { Footer } from 'ts/components/footer'; import { TopBar } from 'ts/components/top_bar/top_bar'; -import { ScreenWidths, WebsitePaths } from 'ts/types'; +import { Deco, Key, ScreenWidths, WebsitePaths } from 'ts/types'; import { colors } from 'ts/utils/colors'; import { constants } from 'ts/utils/constants'; +import { Translate } from 'ts/utils/translate'; import { utils } from 'ts/utils/utils'; interface BoxContent { @@ -36,35 +37,6 @@ interface Project { const THROTTLE_TIMEOUT = 100; -const boxContents: BoxContent[] = [ - { - title: 'Trustless exchange', - description: - "Built on Ethereum's distributed network with no centralized \ - point of failure and no down time, each trade is settled atomically \ - and without counterparty risk.", - imageUrl: '/images/landing/distributed_network.png', - classNames: '', - }, - { - title: 'Shared liquidity', - description: - 'By sharing a standard API, relayers can easily aggregate liquidity pools, \ - creating network effects around liquidity that compound as more relayers come online.', - imageUrl: '/images/landing/liquidity.png', - classNames: 'mx-auto', - }, - { - title: 'Open source', - description: - '0x is open source, permissionless and free to use. Trade directly with a known \ - counterparty for free or pay a relayer some ZRX tokens to access their liquidity \ - pool.', - imageUrl: '/images/landing/open_source.png', - classNames: 'right', - }, -]; - const relayersAndDappProjects: Project[] = [ { logoFileName: 'ethfinex.png', @@ -185,6 +157,7 @@ const relayerProjects: Project[] = [ export interface LandingProps { location: Location; + translate: Translate; } interface LandingState { @@ -193,11 +166,13 @@ interface LandingState { export class Landing extends React.Component { private _throttledScreenWidthUpdate: () => void; + private _translate: Translate; constructor(props: LandingProps) { super(props); this.state = { screenWidth: utils.getScreenWidth(), }; + this._translate = new Translate(); this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT); } public componentDidMount() { @@ -216,17 +191,28 @@ export class Landing extends React.Component { location={this.props.location} isNightVersion={true} style={{ backgroundColor: colors.heroGrey, position: 'relative' }} + translate={this._translate} /> {this._renderHero()} - {this._renderProjects(relayersAndDappProjects, 'Projects building on 0x', colors.projectsGrey, false)} + {this._renderProjects( + relayersAndDappProjects, + this._translate.get(Key.ProjectsHeader, Deco.Upper), + colors.projectsGrey, + false, + )} {this._renderTokenizationSection()} {this._renderProtocolSection()} - {this._renderProjects(relayerProjects, 'Relayers building on 0x', colors.heroGrey, true)} + {this._renderProjects( + relayerProjects, + this._translate.get(Key.RelayersHeader, Deco.Upper), + colors.heroGrey, + true, + )} {this._renderInfoBoxes()} {this._renderBuildingBlocksSection()} {this._renderUseCases()} {this._renderCallToAction()} -