Base solution for your next web application
Open Closed

How should i use read locale browser datetime format ? #8865


User avatar
0
OriAssurant created

Hi ,

we are trying to read local browser datetime format but it seems to be not working for me. we are using angular project with dotnetcore. I tried formatting as mentioned below and then switched my local browser setting my English(US) which has datetime format 4/13/2020 to English(Canada) which has datetime format of 2020-04-13. But it does not seems to be working that way . Can you please guide me ?. I could not find any examples

<td style="width: 150px">
    <span class="ui-column-title">{{'Time' | localize}}</span>
    {{ record.executionTime | momentFormat:'L LTS'}}
</td>

9 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team

    Is your application using ClockProviders.Utc?

    Zero is using the language code as the date format for moment.

    moment.locale(new LocaleMappingService().map('moment', abp.localization.currentLanguage.name));
    (window as any).moment.locale(new LocaleMappingService().map('moment', abp.localization.currentLanguage.name));
    
  • User Avatar
    0
    OriAssurant created

    yes application is using ClockProviders.Utc . We are not asking the user which timezone they live in when users are created and hence we are not setting that in the table. But by default the user's datetime format on all the grids used in the application should be based on their browser datetime format. Can you please guide me with a sample code and what needs to be done on the api side and client side ? I tried using the logic in Appprebootstrap.ts but does not seem to work.

  • User Avatar
    0
    OriAssurant created

    how should i override to use the browser datetime date format instead of this .. moment.locale(new LocaleMappingService().map('moment', abp.localization.currentLanguage.name)); (window as any).moment.locale(new LocaleMappingService().map('moment', abp.localization.currentLanguage.name));

  • User Avatar
    0
    maliming created
    Support Team

    If you confirm that you want to change the localization design of the zero project, you can change the locale of moment in the configureMoment method of AppPreBootstrap.ts.

    private static configureMoment() {
    	// You can also use other methods to get the current language of the browser.
    	var locale = window.navigator.userLanguage || window.navigator.language;
    	moment.locale(locale);
    	(window as any).moment.locale(locale);
    
    
    	if (abp.clock.provider.supportsMultipleTimezone) {
    		moment.tz.setDefault(abp.timing.timeZoneInfo.iana.timeZoneId);
    		(window as any).moment.tz.setDefault(abp.timing.timeZoneInfo.iana.timeZoneId);
    	} else {
    		moment.fn.toJSON = function () {
    			return this.locale('en').format();
    		};
    		moment.fn.toISOString = function () {
    			return this.locale('en').format();
    		};
    	}
    }
    
  • User Avatar
    0
    OriAssurant created

    Hi I could not find the configureMoment method you talked above ? Here's the code from AppPreBootstrap.ts below.

    import { UtilsService } from '@abp/utils/utils.service';
    import { CompilerOptions, NgModuleRef, Type } from '@angular/core';
    import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
    import { AppAuthService } from '@app/shared/common/auth/app-auth.service';
    import { AppConsts } from '@shared/AppConsts';
    import { SubdomainTenancyNameFinder } from '@shared/helpers/SubdomainTenancyNameFinder';
    import * as moment from 'moment';
    import * as _ from 'lodash';
    import { UrlHelper } from './shared/helpers/UrlHelper';
    import { XmlHttpRequestHelper } from '@shared/helpers/XmlHttpRequestHelper';
    import { DynamicResourcesHelper } from '@shared/helpers/DynamicResourcesHelper';
    import { environment } from './environments/environment';
    import { LocaleMappingService } from '@shared/locale-mapping.service';
    
    export class AppPreBootstrap {
    
        static run(appRootUrl: string, callback: () => void, resolve: any, reject: any): void {
            AppPreBootstrap.getApplicationConfig(appRootUrl, () => {
                if (UrlHelper.isInstallUrl(location.href)) {
                    AppPreBootstrap.loadAssetsForInstallPage(callback);
                    return;
                }
    
                const queryStringObj = UrlHelper.getQueryParameters();
    
                if (queryStringObj.redirect && queryStringObj.redirect === 'TenantRegistration') {
                    if (queryStringObj.forceNewRegistration) {
                        new AppAuthService().logout();
                    }
    
                    location.href = AppConsts.appBaseUrl + '/account/select-edition';
                } else if (queryStringObj.impersonationToken) {
                    AppPreBootstrap.impersonatedAuthenticate(queryStringObj.impersonationToken, queryStringObj.tenantId, () => { AppPreBootstrap.getUserConfiguration(callback); });
                } else if (queryStringObj.switchAccountToken) {
                    AppPreBootstrap.linkedAccountAuthenticate(queryStringObj.switchAccountToken, queryStringObj.tenantId, () => { AppPreBootstrap.getUserConfiguration(callback); });
                } else {
                    AppPreBootstrap.getUserConfiguration(callback);
                }
            });
        }
    
        static bootstrap<TM>(moduleType: Type<TM>, compilerOptions?: CompilerOptions | CompilerOptions[]): Promise<NgModuleRef<TM>> {
            return platformBrowserDynamic().bootstrapModule(moduleType, compilerOptions);
        }
    
        private static getApplicationConfig(appRootUrl: string, callback: () => void) {
            let type = 'GET';
            let url = appRootUrl + 'assets/' + environment.appConfig;
            let customHeaders = [
                {
                    name: 'Abp.TenantId',
                    value: abp.multiTenancy.getTenantIdCookie() + ''
                }];
    
            XmlHttpRequestHelper.ajax(type, url, customHeaders, null, (result) => {
                const subdomainTenancyNameFinder = new SubdomainTenancyNameFinder();
                const tenancyName = subdomainTenancyNameFinder.getCurrentTenancyNameOrNull(result.appBaseUrl);
    
                // CUSTOM ADDITION HERE
                let getTenantIdURL = result.remoteServiceBaseUrl + '/api/services/app/Account/IsTenantAvailable';
                let getTenantIdData = {tenancyName: tenancyName};
    
                XmlHttpRequestHelper.ajax('POST', getTenantIdURL, null, JSON.stringify(getTenantIdData), (tenantResult) => {
                    abp.multiTenancy.setTenantIdCookie(tenantResult.result.tenantId);
    
                    AppConsts.appBaseUrlFormat = result.appBaseUrl;
                    AppConsts.remoteServiceBaseUrlFormat = result.remoteServiceBaseUrl;
                    AppConsts.localeMappings = result.localeMappings;
    
                    if (tenancyName == null) {
                        AppConsts.appBaseUrl = result.appBaseUrl.replace(AppConsts.tenancyNamePlaceHolderInUrl + '.', '');
                        //AppConsts.remoteServiceBaseUrl = result.remoteServiceBaseUrl.replace(AppConsts.tenancyNamePlaceHolderInUrl + '.', '');
                    } else {
                        AppConsts.appBaseUrl = result.appBaseUrl.replace(AppConsts.tenancyNamePlaceHolderInUrl, tenancyName);
                        //AppConsts.remoteServiceBaseUrl = result.remoteServiceBaseUrl.replace(AppConsts.tenancyNamePlaceHolderInUrl, tenancyName);
                    }
                    AppConsts.remoteServiceBaseUrl = result.remoteServiceBaseUrl;
    
                    callback();
                });
            });
        }
    
        private static getCurrentClockProvider(currentProviderName: string): abp.timing.IClockProvider {
            if (currentProviderName === 'unspecifiedClockProvider') {
                return abp.timing.unspecifiedClockProvider;
            }
    
            if (currentProviderName === 'utcClockProvider') {
                return abp.timing.utcClockProvider;
            }
    
            return abp.timing.localClockProvider;
        }
    
        private static impersonatedAuthenticate(impersonationToken: string, tenantId: number, callback: () => void): void {
            abp.multiTenancy.setTenantIdCookie(tenantId);
            const cookieLangValue = abp.utils.getCookieValue('Abp.Localization.CultureName');
    
            let requestHeaders = {
                '.AspNetCore.Culture': ('c=' + cookieLangValue + '|uic=' + cookieLangValue),
                'Abp.TenantId': abp.multiTenancy.getTenantIdCookie()
            };
    
            XmlHttpRequestHelper.ajax(
                'POST',
                AppConsts.remoteServiceBaseUrl + '/api/TokenAuth/ImpersonatedAuthenticate?impersonationToken=' + impersonationToken,
                requestHeaders,
                null,
                (response) => {
                    let result = response.result;
                    abp.auth.setToken(result.accessToken);
                    AppPreBootstrap.setEncryptedTokenCookie(result.encryptedAccessToken);
                    location.search = '';
                    callback();
                }
            );
        }
    
        private static linkedAccountAuthenticate(switchAccountToken: string, tenantId: number, callback: () => void): void {
            abp.multiTenancy.setTenantIdCookie(tenantId);
            const cookieLangValue = abp.utils.getCookieValue('Abp.Localization.CultureName');
    
            let requestHeaders = {
                '.AspNetCore.Culture': ('c=' + cookieLangValue + '|uic=' + cookieLangValue),
                'Abp.TenantId': abp.multiTenancy.getTenantIdCookie()
            };
    
            XmlHttpRequestHelper.ajax(
                'POST',
                AppConsts.remoteServiceBaseUrl + '/api/TokenAuth/LinkedAccountAuthenticate?switchAccountToken=' + switchAccountToken,
                requestHeaders,
                null,
                (response) => {
                    let result = response.result;
                    abp.auth.setToken(result.accessToken);
                    AppPreBootstrap.setEncryptedTokenCookie(result.encryptedAccessToken);
                    location.search = '';
                    callback();
                }
            );
        }
    
        private static getUserConfiguration(callback: () => void): any {
            const cookieLangValue = abp.utils.getCookieValue('Abp.Localization.CultureName');
            const token = abp.auth.getToken();
    
            let requestHeaders = {
                '.AspNetCore.Culture': ('c=' + cookieLangValue + '|uic=' + cookieLangValue),
                'Abp.TenantId': abp.multiTenancy.getTenantIdCookie(),
                'Access-Control-Allow-Origin': '*',
                'Access-Control-Allow-Methods': 'GET,PUT,POST'
            };
    
            if (token) {
                requestHeaders['Authorization'] = 'Bearer ' + token;
            }
    
            return XmlHttpRequestHelper.ajax('GET', AppConsts.remoteServiceBaseUrl + '/AbpUserConfiguration/GetAll', requestHeaders, null, (response) => {
                let result = JSON.parse(response).result;
    
                _.merge(abp, result);
    
                abp.clock.provider = this.getCurrentClockProvider(result.clock.provider);
    
                moment.locale(new LocaleMappingService().map('moment', abp.localization.currentLanguage.name));
                (window as any).moment.locale(new LocaleMappingService().map('moment', abp.localization.currentLanguage.name));
                console.log('Should be removed after yarn: ', moment);
                if (abp.clock.provider.supportsMultipleTimezone) {
                    moment.tz.setDefault(abp.timing.timeZoneInfo.iana.timeZoneId);
                    (window as any).moment.tz.setDefault(abp.timing.timeZoneInfo.iana.timeZoneId);
                }
    
                abp.event.trigger('abp.dynamicScriptsInitialized');
    
                AppConsts.recaptchaSiteKey = abp.setting.get('Recaptcha.SiteKey');
                AppConsts.subscriptionExpireNootifyDayCount = parseInt(abp.setting.get('App.TenantManagement.SubscriptionExpireNotifyDayCount'));
    
                DynamicResourcesHelper.loadResources(callback);
            });
        }
    
        private static setEncryptedTokenCookie(encryptedToken: string) {
            new UtilsService().setCookieValue(AppConsts.authorization.encrptedAuthTokenName,
                encryptedToken,
                new Date(new Date().getTime() + 365 * 86400000), //1 year
                abp.appPath
            );
        }
    
        private static loadAssetsForInstallPage(callback) {
            abp.setting.values['App.UiManagement.Theme'] = 'default';
            abp.setting.values['default.App.UiManagement.ThemeColor'] = 'default';
    
            DynamicResourcesHelper.loadResources(callback);
        }
    }
    
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    This service has been refactored. @maliming shared the latest version. But, in your case you need to use browser's locale code for lines below;

    moment.locale(new LocaleMappingService().map('moment', abp.localization.currentLanguage.name));
    (window as any).moment.locale(new LocaleMappingService().map('moment', abp.localization.currentLanguage.name));
    

    You can access browser's language code using navigator.language but this provides en-US format culture code. So, you can basically use;

    moment.locale(navigator.language);
    (window as any).moment.locale(navigator.language);
    
  • User Avatar
    0
    OriAssurant created

    Thanks for your response.. Our requirement is for example in canada - they have 2 lanaguages . english and french. we want the keep date format 2020-04-13 for both these languages based on their browser settings. . The language text needs to change based on the language they select from the Languages dropdown . But the date format on all the grids needs to be driven based on the browser settings ? Does so does this code take care of all browsers ?

    moment.locale(navigator.language); (window as any).moment.locale(navigator.language);

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @OriAssurant

    Yes, setting moment.locale will change the date format in your grids if you are using momentFormat pipe. I'm not sure how it will work in your case for returning the correct language. You can test it in two different user's browsers. Just ask them to press F12 in chrome and paste this code (navigator.language) to browsers console. It will output the browsers language like below.

    For more information, you can check https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/language

  • User Avatar
    0
    OriAssurant created

    thanks a lot for you help. It works fine now.