Swiftpack.co - Package - nodes-vapor/nstack

NStack 🛠

Swift Version Vapor Version CircleCI codebeat badge codecov Readme Score GitHub license

This package is a wrapper around the NStack.io API.

Supports the following NStack modules:

  • Translate

📦 Installation


Add NStack to the Package dependencies:

dependencies: [
    // ...,
    .package(url: "https://github.com/nodes-vapor/nstack.git", .upToNextMajor(from: "3.0.0-beta"))

as well as to your target (e.g. "App"):

targets: [
    .target(name: "App", dependencies: [..., "NStack", ...]),
    // ...

Getting started 🚀

Import NStack where needed:

import NStack


Create NStack.Config to configure NStack, your Applications as well as the default Translate.Config.

let nstackConfig = NStack.Config(
    applicationConfigs: [
            name: "my app name",
            applicationId: "NEVER_PUT_API_IDS_IN_SOURCE_CODE",
            restKey: "NEVER_PUT_API_KEYS_IN_SOURCE_CODE",
    defaultTranslateConfig: TranslateController.Config(
        defaultPlatform: .backend,
        defaultLanguage: "en-EN",
        cacheInMinutes: 1
    log: false

If you set log to true you will receive helpful logs in case anything goes wrong.

Adding the Service

Instantiate and register NStackProvider with config created in the previous step. If you plan on using the leaf tag (see below), make sure to use a synchronous cache, such as MemoryKeyedCache (and not RedisCache); otherwise it might break your leaf templates, see https://github.com/vapor/leaf/issues/134

In configure.swift:

// MARK: NStack
try services.register(
        config: nstackConfig,
        cacheFactory: { container in try container.make(MemoryKeyedCache.self) }


func getProductName(req: Request) throws -> Future<String> {

    // ...

    let nstack = try req.make(NStack.self)
    let translation = nstack.application.translate.get(on: req, section: "products", key: "nstackForSale")

    return translation

You can also provide searchReplacePairs:

func getProductName(req: Request, owner: String) throws -> Future<String> {

    let nstack = try req.make(NStack.self)
    let translation = nstack.application.translate.get(
        on: req,
        section: "products",
        key: "nstackForSale",
        searchReplacePairs: [
            "productOwner" : owner

    return translation

If you are using multiple NStack applications within your project you can switch them with getApplication():

let nstack = try req.make(NStack.self)
let translation = nstack.getApplication("my app name").translate.get(on: req, section: "products", key: "nstackForSale")

Note: you can specify the get() call further in case you don't want to go with the values provided in defaultTranslateConfig:

let translation = nstack.application.translate.get(
    on: req,
    platform: .backend,
    language: "dk-DK",
    section: "products",
    key: "nstackForSale",
    searchReplacePairs: [
        "productOwner" : "Christian"


NStack uses the KeyedCache registered with Vapor. If you don't register any Cache, this should be the KeyedMemory Cache. If you configure Vapor to prefer another Cache, NStack will use this one instead. Example for Redis:

In configure.swift:

config.prefer(DatabaseKeyedCache<ConfiguredDatabase<RedisDatabase>>.self, for: KeyedCache.self)

Leaf Tag

In order to render the NStack Leaf tags, you will need to add them first:

public func configure(_ config: inout Config, _ env: inout Environment, _ services: inout Services) throws {
    services.register { container -> LeafTagConfig in
        var tags = LeafTagConfig.default()
        try tags.useNStackLeafTags(container)
        return tags

NStack comes with a built-in Leaf tag. The tag yields a translated string or the given key if translation fails

// Get translation for camelCasedSection.camelCasedKey
#nstack:translate("camelCasedSection", "camelCasedKey")

// Get translation for camelCasedSection.camelCasedKey and replace searchString1 with replaceString1 etc
#nstack:translate("camelCasedSection", "camelCasedKey", "searchString1", "replaceString1", "searchString2", "replaceString2", ...)

IMPORTANT: Due to a bug in leaf you have to make sure that the translations are already loaded and available synchronously when rendering the view. This can be achieved by using the NStackPreloadMiddleware on the routes for your views:

let nstackPreloadMiddleware = try container.make(NStackPreloadMiddleware.self)
let unprotectedBackend = router.grouped(nstackPreloadMiddleware)

Please note that the leaf tag always uses the current application with the default translate config that you have provided.

🏆 Credits

This package is developed and maintained by the Vapor team at Nodes. The package owner for this project is Christian.

📄 License

This package is open-sourced software licensed under the MIT license


Stars: 6
Help us keep the lights on


Used By

Total: 1


3.0.0-beta.5 - Mar 27, 2019


  • works around the leaf issue (see vapor/leaf#134) by introducing a middleware to preload content


  • Adds an option to specify the KeyedCache used for NStack

3.0.0-beta.4 - Mar 21, 2019


  • brings back placeholder (search/replace) functionality

3.0.0-beta.3 - Jan 22, 2019


  • applies default translation config to Applications

3.0.0-beta.2 - Dec 11, 2018


  • Remove dependency to Sugar and MutableLeafTagConfig

2.0.5 - Nov 15, 2018


  • Section fetch now takes language parameter (Locale string)