Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

not a function #2

Closed
AirMike opened this issue Jun 13, 2016 · 74 comments
Closed

not a function #2

AirMike opened this issue Jun 13, 2016 · 74 comments

Comments

@AirMike
Copy link
Contributor

AirMike commented Jun 13, 2016

Hi, I'm trying to use this package with ns-angular2.

I included
require('nativescript-i18n');

after
import {nativeScriptBootstrap} from "nativescript-angular/application";

in main.ts file and later when I use translation in xml file

<Button text="{{ L('Login') }}"></Button>

I get error:

EXCEPTION: Error in pages/login/login.html:30:8
ORIGINAL EXCEPTION: TypeError: self.context.L is not a function
ORIGINAL STACKTRACE:
TypeError: self.context.L is not a function
    at DebugAppView._View_LoginPage0.detectChangesInternal (LoginPage.template.js:282:56)
@rborn
Copy link
Collaborator

rborn commented Jun 13, 2016

Hi,
I'm sorry but my angular knowledge is close to zero.
However, did you try to require the module the first thing in main.ts ? You say I included...*after*.

@AirMike
Copy link
Contributor Author

AirMike commented Jun 13, 2016

I included it after first import because this import sets globals and other stuff.
Same error is if I put this two lines as the top two lines

@rborn
Copy link
Collaborator

rborn commented Jun 13, 2016

😞
I'll need to have a look and try to find a fix, but it will take a while.
Thank you for letting me know.

@rborn rborn added the angular label Jun 27, 2016
@jamlfy
Copy link

jamlfy commented Jul 20, 2016

Is simple

import "nativescript-angular/application";
import {Pipe, Injectable} from '@angular/core';

@Pipe({
    name: 'i18n',
    pure: false
})
@Injectable()
export class i18n {
      transform(str, args) {
           agrs.push(str);
            return global.L.apply(this, agrs.reverse());
     }
}

In the html

<Button text="{{ i18n:'Login' }}"></Button>

That's all!! 👍

@rborn
Copy link
Collaborator

rborn commented Jul 21, 2016

@alejonext thanks for finding this.

I wonder why the L function is not available in angular if we make it global and also available in resources.

I'll amend the readme with this instructions :)

Thanks again!

@rborn
Copy link
Collaborator

rborn commented Jul 21, 2016

@AirMike could you give a try to #6 ?
Thnx 😄

@loloof64
Copy link
Contributor

loloof64 commented Jul 27, 2016

Hi everyone, I've tried to use the solution from @alejonext , but I did not manage.
Thanks in advance for any help.

MY_PROJECT/utils/i18n.ts

import {Pipe, Injectable} from '@angular/core';

@Pipe({
    name: 'i18n',
    pure: false
})
@Injectable()
export class I18n {
      transform(str, args) {
           args.push(str);
            return global.L.apply(this, args.reverse());
     }
}

MY_PROJECT/main.ts

// this import should be first in order to load some required settings (like globals and reflect-metadata)
import {nativeScriptBootstrap} from "nativescript-angular/application";
require('nativescript-i18n');
import {I18n} from "./utils/i18n";
import {Explorer} from "./components/explorer/explorer";

nativeScriptBootstrap(Explorer, [I18n]);

MY_PROJECT/components/explorer/explorer.ts

import {Component, ViewChild, ElementRef} from "@angular/core";
import {ExplorerItem} from "./explorer_item";
import {Image} from "ui/image";
import fsModule = require("file-system");
import {Folder} from "file-system";
import enumsModule = require("ui/enums");
import animationModule = require("ui/animation");
import {I18n} from "../../utils/i18n";

@Component({
    moduleId: module.id,
    selector: "my-app",
    templateUrl: "explorer.html",
    styleUrls: ["explorer.css"]
})
export class Explorer {

    constructor(I18n: I18n){
        let documentsFolder = fsModule.knownFolders.documents();
        this._docsRootPath = documentsFolder.getFolder("ExercisesCupboard")
        this._currentPath = this._docsRootPath;

        this.updateFilesList();
    } 

    files(){
        return this._files;
    }

    fileImageBase64(){
        return this._fileImageBase64
    }

    folderImageBase64(){
        return this._folderImageBase64
    }

    updateFilesList(){
        this._currentPath.getEntities().then(
            (entities) => {
                this._files = [];
                entities.forEach(element => {
                    this._files.push(new ExplorerItem(element.name, element instanceof Folder));
                });
            },
            function(error) {
                alert("Could not load current folder content !");
            }
        )
    }

    createNewFile(){

    }

    createNewFolder(){

    }

    toggleMenuCreateElements(){

        let fileMenuAnimationOut = {
             translate: {x: -40, y: 0}, opacity: 1,
             duration: 500, curve: enumsModule.AnimationCurve.easeOut,
            };
        let folderMenuAnimationOut = {
            translate: {x: 40, y: 0}, opacity: 1,
            duration: 500, curve: enumsModule.AnimationCurve.easeOut
        };
        let fileMenuAnimationIn = {
             translate: {x: 40, y: 0}, opacity: 0,
             duration: 500, curve: enumsModule.AnimationCurve.easeIn
            };
        let folderMenuAnimationIn = {
            translate: {x: -40, y: 0}, opacity: 0,
            duration: 500, curve: enumsModule.AnimationCurve.easeIn
        };

        if (this._menuCreateElementsIsOpen){
            this._menuButtonCreateNewFile.nativeElement.animate(fileMenuAnimationIn);
            this._menuButtonCreateNewFileLabel.nativeElement.animate(fileMenuAnimationIn);
            this._menuButtonCreateNewFolder.nativeElement.animate(folderMenuAnimationIn);
            this._menuButtonCreateNewFolderLabel.nativeElement.animate(folderMenuAnimationIn);
            this._menuCreateElementsIsOpen = false;
        }
        else {
            this._menuButtonCreateNewFile.nativeElement.animate(fileMenuAnimationOut);
            this._menuButtonCreateNewFileLabel.nativeElement.animate(fileMenuAnimationOut);
            this._menuButtonCreateNewFolder.nativeElement.animate(folderMenuAnimationOut);
            this._menuButtonCreateNewFolderLabel.nativeElement.animate(folderMenuAnimationOut);
            this._menuCreateElementsIsOpen = true;
        }

    }

    @ViewChild('menu_create_elements_file') _menuButtonCreateNewFile:ElementRef;
    @ViewChild('menu_create_elements_file_lbl') _menuButtonCreateNewFileLabel:ElementRef;
    @ViewChild('menu_create_elements_folder') _menuButtonCreateNewFolder:ElementRef;
    @ViewChild('menu_create_elements_folder_lbl')     _menuButtonCreateNewFolderLabel:ElementRef;
    private _menuCreateElementsIsOpen:boolean = false;
    private _docsRootPath: Folder;
    private _currentPath: Folder;

    private _files: Array<ExplorerItem>;

    private _fileImageBase64: string = 'BASE64_IMAGE';

    private _folderImageBase64: string = 'BASE64_IMAGE'
}

MY_PROJECT/components/explorer/explorer.html

<GridLayout rows="*, auto">
    <ListView row="0" [items]="files()">
        <template let-item="item">
            <GridLayout columns="1*, 7*">
                <Image col="0" [src]="item.isDirectory()? folderImageBase64() : fileImageBase64()"></Image>
                <Label col="1" [text]="item.name()" textWrap="true"></Label>
            </GridLayout>
        </template>
    </ListView>

    <StackLayout row="1">
        <Image row="0" #menu_create_elements_file src="~/images/icon_file.png"
 (tap)="createNewFile()" class="fab-button fab-hidden"></Image>
        <label row="1" #menu_create_elements_file_lbl text="{{i18n:'menuitem_file'}" class="fab-label fab-hidden"></label>
    </StackLayout>

    <StackLayout row="1">
        <Image row="0" #menu_create_elements_folder src="~/images/icon_folder.png"
 (tap)="createNewFolder()" row="1" class="fab-button fab-hidden"></Image>
        <label row="1" #menu_create_elements_folder_lbl text="{{i18n:'menuitem_folder'}}" class="fab-label fab-hidden"></label>
    </StackLayout>

    <StackLayout row="1">
        <Image row="0" src="~/images/icon_plus.png"
 (tap)="toggleMenuCreateElements()" class="fab-button"></Image>
        <label row="1" text="{{i18n:'menuitem_new'}}" class="fab-label"></label>
    </StackLayout>


</GridLayout>

@AirMike
Copy link
Contributor Author

AirMike commented Jul 27, 2016

Well, I had some other issues regarding NativeScript and Angular2 so I decided not to go with Angular2 at this moment and I have no issues with this plugin when used without Angular2.

@AirMike AirMike closed this as completed Jul 27, 2016
@AirMike AirMike reopened this Jul 27, 2016
@AirMike
Copy link
Contributor Author

AirMike commented Jul 27, 2016

Just found old version of my project when I was using Angular2 so I will try suggested solution on my project.

@rborn
Copy link
Collaborator

rborn commented Jul 27, 2016

@loloof64 stupid question: did you import the @alejonext branch? Thanks :)

@loloof64
Copy link
Contributor

Not a stupid question, as it appears that I did not know there is the @alejonext branch.
What is the simpliest way of doing this, please ?

@loloof64
Copy link
Contributor

Oh : just found #6.
How can I import it into my project ? (I don't know very much git commands, sorry 😢)

@rborn
Copy link
Collaborator

rborn commented Jul 27, 2016

I think you have 2 ways:

  • remove the module from the project and install it with npm install --save https:/alejonext/nativescript-i18n
  • download his repo as zip and replace by hand all the files in my module

:)

@loloof64
Copy link
Contributor

Thanks I'll try it right now 😃

@loloof64
Copy link
Contributor

Sorry, but I am trying to solve npm depencies issues.
I'll notify you whenever I manage to translate my application.

Later I will have to go, but as soon as I come back, I'll try again.

@AirMike
Copy link
Contributor Author

AirMike commented Jul 27, 2016

I found a way how to make this work (I'm using original nativescript-i18n plugin)
I'm new to Angular2 so I'm not sure how to make this as part of the plugin.

Key is to make custom Angular2 Pipe and make it global so you can use it in any template.

In main.ts after adding:

require('globals'); require('nativescript-i18n');

add this:

`import {provide, PLATFORM_PIPES} from '@angular/core';
import {Pipe, PipeTransform} from '@angular/core';

@pipe({name: 'i18n'})
export class i18n implements PipeTransform {
transform(value: string, more: string): string {
return global.L(value, more);
}
}`

To make this pipe available globally we must use it in bootstrapping application, so add this in main.ts nativeScriptBootstrap:

nativeScriptBootstrap(AppComponent, [ provide(PLATFORM_PIPES, {useValue: [i18n], multi: true}) ]);

After that, in you template file you can use this pipe like this:

<Button class="login-button" text="{{ 'Login' | i18n }}" (tap)="login()"></Button>

@rborn
Copy link
Collaborator

rborn commented Jul 27, 2016

@AirMike could you provide a test case project I could play with?
I don't know anything about angular but I could try to mess with your code and the plugin and maybe I can find a way to make this work within the plugin.

Tbh, this angular stuff (all the pipes and transforms) you have to do to make it work looks to me like being against any purpose of a plugin. It should work out if the box with minimal changes to the code :(

Thanks for your help 😸

@loloof64
Copy link
Contributor

loloof64 commented Jul 27, 2016

Hi again. I've tried to resolve the mess I put in my package.json, but I still can't start my application.
@AirMike do you agree to give me the content of your package.json (or at least to tell me all the dependencies you added for the translation to work) ?

Edit.
I think this is not a problem with package.json, but with the hooks folder I manually deleted. So I'll checkout to my last commit and try with it.

Regards

@jamlfy
Copy link

jamlfy commented Jul 27, 2016

The code in the branch, works in typescript in Angular2 and the code in this issuse is in ES6. The documentation (3 mouths ago) typescript and Angular2, thas code in the branch in funciontal. And construct the App is this main.ts

require('globals'); 
// Use alejonext/nativescript-i18n
import i18n form 'nativescript-i18n/angular';  
// Or
import i18n form './util/i18n';
// More Code
nativeScriptBootstrap(AppComponent, [ 
    provide(PLATFORM_PIPES, {
         useValue: [i18n], 
         multi: true
     })
]);

The file ./util/i18n is the same for that https:/alejonext/nativescript-i18n/blob/master/angular.ts And! That install 'nativescript-i18n'..

Note: Puts the result or a example in the #6 please!!

@loloof64
Copy link
Contributor

loloof64 commented Jul 27, 2016

I can definitely confirm that the translation works with the steps given by @AirMike . I tested it with the french locale in the emulator settings.

Just one line I've added for android not to complain about reflect-metada

import "reflect-metadata";

just below

require("nativescript-i18n");

Here is my project,with which you can play if you want. (Support for english and french).

Just two things I did not test

  • the use of parameters (%s, %d)
  • and whether %d is recognized, as well as %f precision, or not.

(@alejonext : I've tried with the steps from @AirMike , which seems to be inspired by your pull request).

@AirMike
Copy link
Contributor Author

AirMike commented Jul 28, 2016

I can confirm that @alejonext branche is working but only if I add generated angular.js file to the repository (see my forked repository - link bellow).

Also I have suggestion to tweak it a little bit so it will look nicer when used.

If we add one more import in angular.ts file at the top:

import {provide, PLATFORM_PIPES} from '@angular/core';

and then at the bottom add export (in the same angular.ts file):

export const I18N_PROVIDERS = [provide(PLATFORM_PIPES, {useValue: [i18n], multi: true})];

Then when plugin is installed you can import it like this (main.ts file - please note /angular part in the import):

import {I18N_PROVIDERS} from "nativescript-i18n/angular";

Then in the nativeScriptBootstrap just add this:

nativeScriptBootstrap(AppComponent, [I18N_PROVIDERS]);

You can see suggested changes in angular.ts file here and generated angular.js file here and try using this fork: https:/AirMike/nativescript-i18n (npm install --save https:/AirMike/nativescript-i18n)

@loloof64 : you can always manually delete folders hooks and node_modules and than just do npm update to fresh install all npm dependecies and it is suggested that those folders are not pushed to repository

@loloof64
Copy link
Contributor

@AirMike thank you. I did not know about npm update command. So I can safely remove this hooks folder from my repository.

@rborn
Copy link
Collaborator

rborn commented Jul 28, 2016

@AirMike @loloof64 thank you so much for testing and finding a fix for this
and of course @alejonext for providing the initial fix 🙇 🙇 🙇 🙇

I have few questions 😄

  • could you make a PR out of this for the angular.js file (would be only the js file and modified from the generated one to be more readable)
  • could we use in this file the decorate plugin to avoid the ugly decorate definition on top
  • could we change the useValue: [i18n] directive into useValue: [L] to keep it consistent with the plugin's normal usage (just asking, not sure if this is an angular restriction)

Thanks again 😸

@AirMike
Copy link
Contributor Author

AirMike commented Jul 28, 2016

I will make i change with function name and if everything work make a PR.

Regarding decorate definition: this is something that is automatically generated by TypeScript meaning that all coding is done in ts file and TypeScript then generates js file as it see it.
I'm not expert in Angular, but this plugin you mentioned is for AngularJS with is something completely different from Angular2 (as far as I know)

@rborn
Copy link
Collaborator

rborn commented Jul 28, 2016

@AirMike ok, I think I can live with a ts file in the plugin :)
Thanks again.

@rborn
Copy link
Collaborator

rborn commented Jul 28, 2016

@AirMike @loloof64 @alejonext I merged the PR and updated the Readme. Could you guys have a look if the instructions are ok?

Thanks again for all your help 🍻

@loloof64
Copy link
Contributor

Yes, maybe something can be improved in the pipe.
I tried to put variadics with (inside angular.ts)

export class L implements PipeTransform {
    transform(value: string, ...more: string[]): string {
        return global.L(value, ...more);
    }
}

but it did not work either.

@rborn
Copy link
Collaborator

rborn commented Jul 28, 2016

I think you need to do it in angular.js too ?

@loloof64
Copy link
Contributor

loloof64 commented Jul 28, 2016

Ah maybe. I did not think about that. I'll see if I can manage.
In fact I forgot the js version is generated from the typescript file, so it is really from the ts file that the modification must be done.

@loloof64
Copy link
Contributor

It works !
Maybe because I didn't run accordingly on the phone the first time, I thought that the variadic method didn't work. But it is the solution.

What are the steps for a Pull Request : I must first clone your repository and launch a PR : right ?

@rborn
Copy link
Collaborator

rborn commented Jul 28, 2016

Amazing :)

For the PR this should do it:

  • fork my repo on github with the fork button
  • clone your repo on your computer, make your changes and push them against your repo
  • create a PR from the github page

😄

@loloof64
Copy link
Contributor

Thanks 😄

I do it right now.

@loloof64
Copy link
Contributor

loloof64 commented Jul 28, 2016

Done PR 😄
I will test it with your updated version instead of mine for me to be sure that the PR is good.

@rborn
Copy link
Collaborator

rborn commented Jul 28, 2016

After I merge the PR and update npm you can test it just like any other dev 😸

@loloof64
Copy link
Contributor

Yes. That's right, anybody will be able to notify a problem about the new version. 😄

@rborn
Copy link
Collaborator

rborn commented Jul 28, 2016

The point is that I want to push the changes so you can test with the real thing :)

@loloof64
Copy link
Contributor

No problem 😄 I'll test it as soon as you released it 😄

@rborn
Copy link
Collaborator

rborn commented Jul 28, 2016

I added a comment on the PR

@loloof64
Copy link
Contributor

I've updated the README on my PR with a detailed use case 😄

@rborn
Copy link
Collaborator

rborn commented Jul 28, 2016

Merged, bumped and published to npm 🎉
You should be able to test with the normal install sequence now.

Thanks again 😄

@loloof64
Copy link
Contributor

You're welcome 😄

I've just tested the plugin using the normal installation sequence, and it works like before : as expected 😄

@rborn
Copy link
Collaborator

rborn commented Jul 28, 2016

Yay 🙌🙌🙌🙌

Sent from my iPhone

On Jul 28, 2016, at 8:32 PM, laurent bernabé [email protected] wrote:

You're welcome 😄

I've just tested the plugin using the normal installation sequence, and it works like before : as expected 😄


You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.

@jamlfy
Copy link

jamlfy commented Jul 28, 2016

👍 😋

@rborn rborn closed this as completed Jul 28, 2016
@loloof64
Copy link
Contributor

loloof64 commented Jul 31, 2016

Hello again.

I've just noticed that, in TypeScript code, one has just to invoke global.L() instead of L() in order to translate strings. No import is required.

I can update my version of the repository with git pull, modify README, and make a new PR if needed.

Regards.

@rborn
Copy link
Collaborator

rborn commented Aug 3, 2016

Hi, sorry for the late reply.
Are you sure you import globals (trailing s) ?

@loloof64
Copy link
Contributor

loloof64 commented Aug 3, 2016

No, as well as I setup app.ts with I18N_PROVIDER (like noticed in the readme, so the end-user should already have done this), the L function is available by calling global.L (without trailing s) in any typescript file (except the launcher app.ts of course). As simple as that.

So L function can also be used in code-behind in TypeScript without further configuration 😄

@rborn
Copy link
Collaborator

rborn commented Aug 4, 2016

@loloof64 But do you load globals in app.ts ? The equivalent of require('globals');?

@loloof64
Copy link
Contributor

loloof64 commented Aug 4, 2016

No I just have to import the I18N_PROVIDERS, because when I do it, it always import the globals. And if I set it in the bootsrap providers (main application), then it will be available anywhere.

@rborn
Copy link
Collaborator

rborn commented Aug 4, 2016

but not app.ts right? or I'm not understanding the issue? 😆

@loloof64
Copy link
Contributor

loloof64 commented Aug 4, 2016

It's not an issue, it's just a notice that the L function can also be used in TypeScript code, but we don't have to call L() but global.L() instead.

@rborn
Copy link
Collaborator

rborn commented Aug 4, 2016

Mmm, ideally should be the same. I'll try to take a look when I'll have a little time
Thanks for letting me know 😊

Sent from my iPhone

On Aug 4, 2016, at 9:54 PM, laurent bernabé [email protected] wrote:

It's not an issue, it's just a notice that the L function can also be used in TypeScript code, but we don't have to call L() but global.L() instead.


You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub, or mute the thread.

@ivoeersels
Copy link

ivoeersels commented Jan 20, 2017

I am trying to localize an alert message inside a typescript function in a ...component.ts file.
The localization works in the template of that same component.

In 'app.module.ts' of our app I have:

import { NgModule, NO_ERRORS_SCHEMA } from "@angular/core";
import { NativeScriptFormsModule } from "nativescript-angular/forms";
import { NativeScriptHttpModule } from "nativescript-angular/http";
import { NativeScriptI18nModule } from "nativescript-i18n/angular";
import { NativeScriptModule } from "nativescript-angular/platform";
import { NativeScriptRouterModule } from "nativescript-angular/router";
import { AppComponent } from "./app.component";
import { routes, navigatableComponents } from "./app.routing";
@NgModule({
imports: [
NativeScriptModule,
NativeScriptFormsModule,
NativeScriptHttpModule,
NativeScriptI18nModule,
NativeScriptRouterModule,
NativeScriptRouterModule.forRoot(routes)
],
declarations: [
AppComponent,
...navigatableComponents
],
bootstrap: [AppComponent],
schemas: [NO_ERRORS_SCHEMA]
})
export class AppModule { }

But when I try something like alert(L('orderform_add_error_no_sku')); in the ...component.ts the build says it cannot fine name 'L'.
Using alert(global.L('orderform_add_error_no_sku')); didn't work either.

What am I forgetting to do?

EDIT
Apparently I need to include this line 'import { NativeScriptI18nModule } from "nativescript-i18n/angular";' in every .ts file where I want to do this. I had a look at your angular.ts and figured this is needed when transpiling from TypeScript to Javascript

@rborn
Copy link
Collaborator

rborn commented Jan 20, 2017

@ivoeersels I think it's related to #33

@ivoeersels
Copy link

@rborn I am not so sure about it... in issue #33 I mention that the code doesn't even build because NPM not downloading and installing 'angular.ts'. So at that moment nothing worked. After downloading it manually it works but only in the templates, not in the TypeScript component .ts files and that is what I mentioned here.

@rborn
Copy link
Collaborator

rborn commented Jan 23, 2017

@ivoeersels to be honest this is over my head 😢 I don't use typescript and neither angular.
I'll try to push the angular.ts file to npm and finish #11 but I will need help for this issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants